<commit_before>/******************************************************************************

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/
#include "DataSource.h"

#include "OperatorPython.h"
#include "Utilities.h"
#include "vtkDataObject.h"
#include "vtkDoubleArray.h"
#include "vtkExtractVOI.h"
#include "vtkFieldData.h"
#include "vtkNew.h"
#include "vtkImageData.h"
#include "vtkSmartPointer.h"
#include "vtkSMCoreUtilities.h"
#include "vtkSMParaViewPipelineController.h"
#include "vtkSMPropertyHelper.h"
#include "vtkSMSessionProxyManager.h"
#include "vtkSMSourceProxy.h"
#include "vtkSMTransferFunctionManager.h"
#include "vtkTrivialProducer.h"

#include <vtk_pugixml.h>


namespace tomviz
{

class DataSource::DSInternals
{
public:
  vtkSmartPointer<vtkSMSourceProxy> OriginalDataSource;
  vtkWeakPointer<vtkSMSourceProxy> Producer;
  QList<QSharedPointer<Operator> > Operators;
  vtkSmartPointer<vtkSMProxy> ColorMap;
  DataSource::DataSourceType Type;
};

namespace {
void ensureTiltAnglesArrayExists(vtkSMSourceProxy* proxy)
{
  vtkTrivialProducer* tp = vtkTrivialProducer::SafeDownCast(
    proxy->GetClientSideObject());
  vtkDataObject* data = tp->GetOutputDataObject(0);
  vtkFieldData* fd = data->GetFieldData();
  vtkDataArray* tiltAngles = fd->GetArray("tilt_angles");
  int* extent = vtkImageData::SafeDownCast(data)->GetExtent();
  int num_tilt_angles = extent[5] - extent[4] + 1;
  if (tiltAngles == NULL)
  {
    vtkNew< vtkDoubleArray > array;
    array->SetName("tilt_angles");
    array->SetNumberOfTuples(num_tilt_angles);
    array->FillComponent(0,0.0);
    fd->AddArray(array.GetPointer());
  }
}
}

//-----------------------------------------------------------------------------
DataSource::DataSource(vtkSMSourceProxy* dataSource, DataSourceType dataType,
                      QObject* parentObject)
  : Superclass(parentObject),
  Internals(new DataSource::DSInternals())
{
  Q_ASSERT(dataSource);
  this->Internals->OriginalDataSource = dataSource;
  this->Internals->Type = dataType;

  vtkNew<vtkSMParaViewPipelineController> controller;
  vtkSMSessionProxyManager* pxm = dataSource->GetSessionProxyManager();
  Q_ASSERT(pxm);

  vtkSmartPointer<vtkSMProxy> source;
  source.TakeReference(pxm->NewProxy("sources", "TrivialProducer"));
  Q_ASSERT(source != NULL);
  Q_ASSERT(vtkSMSourceProxy::SafeDownCast(source));

  // We add an annotation to the proxy so that it'll be easier for code to
  // locate registered pipeline proxies that are being treated as data sources.
  const char* sourceFilename =
      vtkSMPropertyHelper(dataSource,
                          vtkSMCoreUtilities::GetFileNameProperty(dataSource)).GetAsString();
  if (sourceFilename && strlen(sourceFilename))
    {
    tomviz::annotateDataProducer(source, sourceFilename);
    }
  else if (dataSource->HasAnnotation("filename"))
    {
    cout << source->GetAnnotation("filename");
    tomviz::annotateDataProducer(source, dataSource->GetAnnotation("filename"));
    }

  controller->RegisterPipelineProxy(source);
  this->Internals->Producer = vtkSMSourceProxy::SafeDownCast(source);

  // Setup color map for this data-source.
  static unsigned int colorMapCounter=0;
  colorMapCounter++;

  vtkNew<vtkSMTransferFunctionManager> tfmgr;
  this->Internals->ColorMap = tfmgr->GetColorTransferFunction(
    QString("DataSourceColorMap%1").arg(colorMapCounter).toLatin1().data(), pxm);

  // every time the data changes, we should update the color map.
  this->connect(this, SIGNAL(dataChanged()), SLOT(updateColorMap()));

  this->resetData();
}

//-----------------------------------------------------------------------------
DataSource::~DataSource()
{
  if (this->Internals->Producer)
    {
    vtkNew<vtkSMParaViewPipelineController> controller;
    controller->UnRegisterProxy(this->Internals->Producer);
    }
}

//-----------------------------------------------------------------------------
QString DataSource::filename() const
{
  vtkSMProxy* dataSource = this->originalDataSource();
  return vtkSMPropertyHelper(dataSource,
    vtkSMCoreUtilities::GetFileNameProperty(dataSource)).GetAsString();
}

//-----------------------------------------------------------------------------
bool DataSource::serialize(pugi::xml_node& ns) const
{
  pugi::xml_node node = ns.append_child("ColorMap");
  tomviz::serialize(this->colorMap(), node);

  node = ns.append_child("OpacityMap");
  tomviz::serialize(this->opacityMap(), node);

  ns.append_attribute("number_of_operators").set_value(
    static_cast<int>(this->Internals->Operators.size()));

  foreach (QSharedPointer<Operator> op, this->Internals->Operators)
    {
    pugi::xml_node operatorNode = ns.append_child("Operator");
    if (!op->serialize(operatorNode))
      {
      qWarning("failed to serialize Operator. Skipping it.");
      ns.remove_child(operatorNode);
      }
    }
  return true;
}

//-----------------------------------------------------------------------------
bool DataSource::deserialize(const pugi::xml_node& ns)
{
  tomviz::deserialize(this->colorMap(), ns.child("ColorMap"));
  tomviz::deserialize(this->opacityMap(), ns.child("OpacityMap"));
  vtkSMPropertyHelper(this->colorMap(),
                      "ScalarOpacityFunction").Set(this->opacityMap());
  this->colorMap()->UpdateVTKObjects();
<commit_msg>Type of DataSource is now serialized/deserialized<commit_after>/******************************************************************************

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/
#include "DataSource.h"

#include "OperatorPython.h"
#include "Utilities.h"
#include "vtkDataObject.h"
#include "vtkDoubleArray.h"
#include "vtkExtractVOI.h"
#include "vtkFieldData.h"
#include "vtkNew.h"
#include "vtkImageData.h"
#include "vtkSmartPointer.h"
#include "vtkSMCoreUtilities.h"
#include "vtkSMParaViewPipelineController.h"
#include "vtkSMPropertyHelper.h"
#include "vtkSMSessionProxyManager.h"
#include "vtkSMSourceProxy.h"
#include "vtkSMTransferFunctionManager.h"
#include "vtkTrivialProducer.h"

#include <vtk_pugixml.h>


namespace tomviz
{

class DataSource::DSInternals
{
public:
  vtkSmartPointer<vtkSMSourceProxy> OriginalDataSource;
  vtkWeakPointer<vtkSMSourceProxy> Producer;
  QList<QSharedPointer<Operator> > Operators;
  vtkSmartPointer<vtkSMProxy> ColorMap;
  DataSource::DataSourceType Type;
};

namespace {

// Checks if the tilt angles data array exists on the given VTK data
// and creates it if it does not exist.
void ensureTiltAnglesArrayExists(vtkSMSourceProxy* proxy)
{
  vtkTrivialProducer* tp = vtkTrivialProducer::SafeDownCast(
    proxy->GetClientSideObject());
  vtkDataObject* data = tp->GetOutputDataObject(0);
  vtkFieldData* fd = data->GetFieldData();
  vtkDataArray* tiltAngles = fd->GetArray("tilt_angles");
  int* extent = vtkImageData::SafeDownCast(data)->GetExtent();
  int num_tilt_angles = extent[5] - extent[4] + 1;
  if (tiltAngles == NULL)
  {
    vtkNew< vtkDoubleArray > array;
    array->SetName("tilt_angles");
    array->SetNumberOfTuples(num_tilt_angles);
    array->FillComponent(0,0.0);
    fd->AddArray(array.GetPointer());
  }
}

// Converts the data type to a string for writing to the save state
const char* dataSourceTypeToString(DataSource::DataSourceType type)
{
  switch (type)
    {
    case DataSource::Volume:
      return "volume";
    case DataSource::TiltSeries:
      return "tilt-series";
    default:
      assert("Unhandled data source type" && false);
      return "";
    }
}

// Converts the save state string back to a DataSource::DataSourceType
// Returns true if the type was successfully converted, false otherwise
// the result is stored in the output paremeter type.
bool stringToDataSourceType(const char* str, DataSource::DataSourceType& type)
{
  if (strcmp(str, "volume") == 0)
  {
    type = DataSource::Volume;
    return true;
  }
  else if (strcmp(str, "tilt-series") == 0)
  {
    type = DataSource::TiltSeries;
    return true;
  }
  return false;
}

}

//-----------------------------------------------------------------------------
DataSource::DataSource(vtkSMSourceProxy* dataSource, DataSourceType dataType,
                      QObject* parentObject)
  : Superclass(parentObject),
  Internals(new DataSource::DSInternals())
{
  Q_ASSERT(dataSource);
  this->Internals->OriginalDataSource = dataSource;
  this->Internals->Type = dataType;

  vtkNew<vtkSMParaViewPipelineController> controller;
  vtkSMSessionProxyManager* pxm = dataSource->GetSessionProxyManager();
  Q_ASSERT(pxm);

  vtkSmartPointer<vtkSMProxy> source;
  source.TakeReference(pxm->NewProxy("sources", "TrivialProducer"));
  Q_ASSERT(source != NULL);
  Q_ASSERT(vtkSMSourceProxy::SafeDownCast(source));

  // We add an annotation to the proxy so that it'll be easier for code to
  // locate registered pipeline proxies that are being treated as data sources.
  const char* sourceFilename =
      vtkSMPropertyHelper(dataSource,
                          vtkSMCoreUtilities::GetFileNameProperty(dataSource)).GetAsString();
  if (sourceFilename && strlen(sourceFilename))
    {
    tomviz::annotateDataProducer(source, sourceFilename);
    }
  else if (dataSource->HasAnnotation("filename"))
    {
    cout << source->GetAnnotation("filename");
    tomviz::annotateDataProducer(source, dataSource->GetAnnotation("filename"));
    }

  controller->RegisterPipelineProxy(source);
  this->Internals->Producer = vtkSMSourceProxy::SafeDownCast(source);

  // Setup color map for this data-source.
  static unsigned int colorMapCounter=0;
  colorMapCounter++;

  vtkNew<vtkSMTransferFunctionManager> tfmgr;
  this->Internals->ColorMap = tfmgr->GetColorTransferFunction(
    QString("DataSourceColorMap%1").arg(colorMapCounter).toLatin1().data(), pxm);

  // every time the data changes, we should update the color map.
  this->connect(this, SIGNAL(dataChanged()), SLOT(updateColorMap()));

  this->resetData();
}

//-----------------------------------------------------------------------------
DataSource::~DataSource()
{
  if (this->Internals->Producer)
    {
    vtkNew<vtkSMParaViewPipelineController> controller;
    controller->UnRegisterProxy(this->Internals->Producer);
    }
}

//-----------------------------------------------------------------------------
QString DataSource::filename() const
{
  vtkSMProxy* dataSource = this->originalDataSource();
  return vtkSMPropertyHelper(dataSource,
    vtkSMCoreUtilities::GetFileNameProperty(dataSource)).GetAsString();
}

//-----------------------------------------------------------------------------
bool DataSource::serialize(pugi::xml_node& ns) const
{
  pugi::xml_node node = ns.append_child("ColorMap");
  tomviz::serialize(this->colorMap(), node);

  node = ns.append_child("OpacityMap");
  tomviz::serialize(this->opacityMap(), node);

  ns.append_attribute("number_of_operators").set_value(
    static_cast<int>(this->Internals->Operators.size()));

  ns.append_attribute("type").set_value(
    dataSourceTypeToString(this->type()));

  foreach (QSharedPointer<Operator> op, this->Internals->Operators)
    {
    pugi::xml_node operatorNode = ns.append_child("Operator");
    if (!op->serialize(operatorNode))
      {
      qWarning("failed to serialize Operator. Skipping it.");
      ns.remove_child(operatorNode);
      }
    }
  return true;
}

//-----------------------------------------------------------------------------
bool DataSource::deserialize(const pugi::xml_node& ns)
{
  tomviz::deserialize(this->colorMap(), ns.child("ColorMap"));
  tomviz::deserialize(this->opacityMap(), ns.child("OpacityMap"));
  vtkSMPropertyHelper(this->colorMap(),
                      "ScalarOpacityFunction").Set(this->opacityMap());
  this->colorMap()->UpdateVTKObjects();

  DataSourceType dstype;
  if (!stringToDataSourceType(ns.attribute("type").value(),dstype))
    {
    return false;
    }
  this->setType(dstype);

{'fraction_non_alphanumeric': 0.19743090696769172, 'fraction_numerical': 0.0017127286882055275, 'mean_word_length': 3.6883211678832115, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 121, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 10}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4473830', 'n_tokens_mistral': 3747, 'n_tokens_neox': 3694, 'n_words': 766}