<commit_before>// MRML includes
#include "vtkMRMLAstroVolumeStorageNode.h"
#include "vtkMRMLScene.h"
#include "vtkMRMLVolumeNode.h"
#include "vtkMRMLAstroVolumeNode.h"
#include "vtkMRMLAstroVolumeDisplayNode.h"
#include "vtkMRMLAstroLabelMapVolumeNode.h"
#include "vtkMRMLAstroLabelMapVolumeDisplayNode.h"

//vtkFits includes
#include <vtkFITSReader.h>
#include <vtkFITSWriter.h>

// VTK includes
#include <vtkImageChangeInformation.h>
#include <vtkImageData.h>
#include <vtkNew.h>
#include <vtkObjectFactory.h>
#include <vtkStringArray.h>
#include <vtkVersion.h>
#include <vtkType.h>

//----------------------------------------------------------------------------
vtkMRMLNodeNewMacro(vtkMRMLAstroVolumeStorageNode);

//----------------------------------------------------------------------------
vtkMRMLAstroVolumeStorageNode::vtkMRMLAstroVolumeStorageNode()
{
  this->CenterImage = 0;
}

//----------------------------------------------------------------------------
vtkMRMLAstroVolumeStorageNode::~vtkMRMLAstroVolumeStorageNode()
{
}

namespace
{
//----------------------------------------------------------------------------
template <typename T> std::string NumberToString(T V)
{
  std::string stringValue;
  std::stringstream strstream;
  strstream << V;
  strstream >> stringValue;
  return stringValue;
}

//----------------------------------------------------------------------------
std::string DoubleToString(double Value)
{
  return NumberToString<double>(Value);
}
}//end namespace

//----------------------------------------------------------------------------
void vtkMRMLAstroVolumeStorageNode::WriteXML(ostream& of, int nIndent)
{
  Superclass::WriteXML(of, nIndent);
  vtkIndent indent(nIndent);

  std::stringstream ss;
  ss << this->CenterImage;
  of << indent << " centerImage=\"" << ss.str() << "\"";
}

//----------------------------------------------------------------------------
void vtkMRMLAstroVolumeStorageNode::ReadXMLAttributes(const char** atts)
{
  int disabledModify = this->StartModify();

  Superclass::ReadXMLAttributes(atts);

  const char* attName;
  const char* attValue;
  while (*atts != NULL)
    {
    attName = *(atts++);
    attValue = *(atts++);
    if (!strcmp(attName, "centerImage"))
      {
      std::stringstream ss;
      ss << attValue;
      ss >> this->CenterImage;
      }
    }

  this->EndModify(disabledModify);
}

//----------------------------------------------------------------------------
// Copy the node's attributes to this object.
// Does NOT copy: ID, FilePrefix, Name, StorageID
void vtkMRMLAstroVolumeStorageNode::Copy(vtkMRMLNode *anode)
{
  if (!anode)
    {
    return;
    }

  int disabledModify = this->StartModify();

  Superclass::Copy(anode);
  vtkMRMLAstroVolumeStorageNode *node = (vtkMRMLAstroVolumeStorageNode *) anode;

  this->SetCenterImage(node->CenterImage);

  this->EndModify(disabledModify);
}

//----------------------------------------------------------------------------
void vtkMRMLAstroVolumeStorageNode::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkMRMLStorageNode::PrintSelf(os,indent);
  os << indent << "CenterImage:   " << this->CenterImage << "\n";
}

//----------------------------------------------------------------------------
bool vtkMRMLAstroVolumeStorageNode::CanReadInReferenceNode(vtkMRMLNode *refNode)
{
  return refNode->IsA("vtkMRMLAstroVolumeNode") ||
         refNode->IsA("vtkMRMLAstroLabelMapVolumeNode");
}

//----------------------------------------------------------------------------
int vtkMRMLAstroVolumeStorageNode::ReadDataInternal(vtkMRMLNode *refNode)
{
  vtkMRMLAstroVolumeNode *volNode = NULL;
  vtkMRMLAstroLabelMapVolumeNode *labvolNode = NULL;
  vtkMRMLAstroVolumeDisplayNode *disNode = NULL;
  vtkMRMLAstroLabelMapVolumeDisplayNode *labdisNode = NULL;

  if ( refNode->IsA("vtkMRMLAstroVolumeNode") )
    {
    volNode = dynamic_cast <vtkMRMLAstroVolumeNode *> (refNode);
    disNode = volNode->GetAstroVolumeDisplayNode();
    }
  else if ( refNode->IsA("vtkMRMLAstroLabelMapVolumeNode") )
    {
    labvolNode = dynamic_cast <vtkMRMLAstroLabelMapVolumeNode *> (refNode);
    labdisNode = labvolNode->GetAstroLabelMapVolumeDisplayNode();
    }
  else
    {
    vtkErrorMacro(<< "Do not recognize node type " << refNode->GetClassName());
    return 0;
    }

  vtkNew<vtkFITSReader> reader;

  // Set Reader member variables
  if (this->CenterImage)
    {
    reader->SetUseNativeOriginOff();
    }
  else
    {
    reader->SetUseNativeOriginOn();
    }

  if ( refNode->IsA("vtkMRMLAstroVolumeNode") )
    {
    if (volNode->GetImageData())
      {
      volNode->SetAndObserveImageData (NULL);
      }
    }
  else if ( refNode->IsA("vtkMRMLAstroLabelMapVolumeNode") )
    {
    if (labvolNode->GetImageData())
      {
      labvolNode->SetAndObserveImageData (NULL);
      }
    }

  std::string fullName = this->GetFullNameFromFileName();

  if (fullName == std::string(""))
    {
    vtkErrorMacro("ReadData: File name not specified");
    return 0;
    }

  reader->SetFileName(fullName.c_str());

  // Check if this is a FITS file that we can read
  if (!reader->CanReadFile(fullName.c_str()))
    {
    vtkErrorMacro("ReadData: This is not a fits file");
    return 0;
    }

  // Read the header to see if the file corresponds to the MRML Node
  reader->UpdateInformation();

  if( refNode->IsA("vtkMRMLAstroVolumeNode") || refNode->IsA("vtkMRMLAstroLabelMapVolumeNode") )
    {
    if (reader->GetPointDataType() != vtkDataSetAttributes::SCALARS &&
         reader->GetNumberOfComponents() > 1 )
      {
      vtkErrorMacro("ReadData: MRMLVolumeNode does not match file kind");
      return 0;
      }
    }

  reader->Update();
  if ( refNode->IsA("vtkMRMLAstroVolumeNode") )
    {
    // set volume attributes
    vtkMatrix4x4* mat = reader->GetRasToIjkMatrix();
    volNode->SetRASToIJKMatrix(mat);

    //set WCSstruct
    volNode->SetWCSStruct(reader->GetWCSStruct());

    // parse WCS Status
    volNode->SetWCSStatus(reader->GetWCSStatus());

    // parse non-specific key-value pairs
    std::vector<std::string> keys = reader->GetHeaderKeysVector();
    for ( std::vector<std::string>::iterator kit = keys.begin();
          kit != keys.end(); ++kit)
      {
      volNode->SetAttribute((*kit).c_str(), reader->GetHeaderValue((*kit).c_str()));
      }

    // parse Space (WCS or IJK) to the display node
    if (disNode)
      {
      if (volNode->GetWCSStatus() != 0)
        {
        disNode->SetSpace("IJK");
        }
      if(!strcmp(reader->GetHeaderValue("SlicerAstro.CUNIT3"), "HZ") ||
         !strcmp(reader->GetHeaderValue("SlicerAstro.CUNIT3"), "Hz"))
        {
        disNode->SetSpaceQuantity(2,"frequency");
        }
      }
    if (!strcmp(reader->GetHeaderValue("SlicerAstro.BUNIT"), "W.U."))
      {
      volNode->SetAttribute("SlicerAstro.BUNIT", "JY/BEAM");
      vtkWarningMacro("The flux unit of Volume "<<volNode->GetName()<<
                      " is in Westerbork Unit. It will be automatically converted in JY/BEAM"<<endl);
      }
    }
  else if ( refNode->IsA("vtkMRMLAstroLabelMapVolumeNode") )
    {
    // set volume attributes
    vtkMatrix4x4* mat = reader->GetRasToIjkMatrix();
    labvolNode->SetRASToIJKMatrix(mat);
    //set WCSstruct
    labvolNode->SetWCSStruct(reader->GetWCSStruct());
    // parse WCS Status
    labvolNode->SetWCSStatus(reader->GetWCSStatus());
    // parse non-specific key-value pairs
    std::vector<std::string> keys = reader->GetHeaderKeysVector();
    for ( std::vector<std::string>::iterator kit = keys.begin();
          kit != keys.end(); ++kit)
      {
      labvolNode->SetAttribute((*kit).c_str(), reader->GetHeaderValue((*kit).c_str()));
      }
      // parse Space (WCS or IJK) to the display node
    if (labdisNode)
      {
      if (labvolNode->GetWCSStatus() != 0)
        {
        labdisNode->SetSpace("IJK");
        }
      if(!strcmp(reader->GetHeaderValue("SlicerAstro.CUNIT3"), "HZ") ||
         !strcmp(reader->GetHeaderValue("SlicerAstro.CUNIT3"), "Hz"))
        {
        labdisNode->SetSpaceQuantity(2,"frequency");
        }
      }
    if (!strcmp(reader->GetHeaderValue("SlicerAstro.BUNIT"), "W.U."))
      {
      labvolNode->SetAttribute("SlicerAstro.BUNIT", "JY/BEAM");
      vtkWarningMacro("The flux unit of Volume "<<labvolNode->GetName()<<
                      " is in Westerbork Unit. It will be automatically converted in JY/BEAM"<<endl);
      }
    }
  // rescaling flux and calculating max, min and noise
  if(!strcmp(reader->GetHeaderValue("SlicerAstro.DATAMAX"), "0.") ||
       !strcmp(reader->GetHeaderValue("SlicerAstro.DATAMIN"), "0.") ||
       !strcmp(reader->GetHeaderValue("SlicerAstro.BUNIT"), "W.U.") ||
       !strcmp(reader->GetHeaderValue("SlicerAstro.NOISE"), "0."))
    {
    vtkImageData *imageData = reader->GetOutput();
    int vtkType = reader->GetDataType();
    int *dims = imageData->GetDimensions();
    const int numComponents = imageData->GetNumberOfScalarComponents();
    double max = imageData->GetScalarTypeMin();
    double min = imageData->GetScalarTypeMax();
    double noise = 0.;
    const int numElements = dims[0] * dims[1] * dims[2] * numComponents;
    const int lowBoundary = dims[0] * dims[1] * 2;
    const int highBoundary = dims[0] * dims[1] * 4;
    const int numCropElements = highBoundary - lowBoundary;
    switch (vtkType)
      {
      case VTK_DOUBLE:
        double *dPixel;
        dPixel = static_cast<double*>(imageData->GetScalarPointer(0,0,0));

        if (!strcmp(reader->GetHeaderValue("SlicerAstro.BUNIT"), "W.U."))
          {
          for( int elemCnt = 0; elemCnt < numElements; elemCnt++)
            {
            *(dPixel+elemCnt) *= 0.005;
            }
          }

        if(!strcmp(reader->GetHeaderValue("SlicerAstro.DATAMAX"), "0.") ||
             !strcmp(reader->GetHeaderValue("SlicerAstro.DATAMIN"), "0."))
          {
          for( int elemCnt = 0; elemCnt < numElements; elemCnt++ )
            {
            if(*(dPixel+elemCnt) > max)
              {
              max = *(dPixel+elemCnt);
              }
            if(*(dPixel+elemCnt) < min)
              {
              min = *(dPixel+elemCnt);
              }
            }
          }

        if (!strcmp(reader->GetHeaderValue("SlicerAstro.NOISE"), "0."))
          {
          double sum = 0.;
          for( int elemCnt = lowBoundary; elemCnt < highBoundary; elemCnt++)
            {
            sum += *(dPixel+elemCnt);
            }
          sum /= numCropElements;
          for( int elemCnt = lowBoundary; elemCnt < highBoundary; elemCnt++)
            {
            noise += (*(dPixel+elemCnt) - sum) * (*(dPixel+elemCnt) - sum);
            }
          noise = sqrt(noise / numCropElements);
          }
        break;
      case VTK_FLOAT:
        float *fPixel;
        fPixel = static_cast<float*>(imageData->GetScalarPointer(0,0,0));
        if (!strcmp(reader->GetHeaderValue("SlicerAstro.BUNIT"), "W.U."))
          {
          for( int elemCnt = 0; elemCnt < numElements; elemCnt++)
            {
            *(fPixel+elemCnt) *= 0.005;
            }
          }

        if(!strcmp(reader->GetHeaderValue("SlicerAstro.DATAMAX"), "0.") ||
             !strcmp(reader->GetHeaderValue("SlicerAstro.DATAMIN"), "0."))
          {
          for( int elemCnt = 0; elemCnt < numElements; elemCnt++ )
            {
            if(*(fPixel+elemCnt) > max)
              {
              max = *(fPixel+elemCnt);
              }
            if(*(fPixel+elemCnt) < min)
              {
              min = *(fPixel+elemCnt);
              }
            }
          }

        if (!strcmp(reader->GetHeaderValue("SlicerAstro.NOISE"), "0."))
          {
          double sum = 0.;
          for( int elemCnt = lowBoundary; elemCnt < highBoundary; elemCnt++)
            {
            sum += *(fPixel+elemCnt);
            }
          sum /= numCropElements;
          for( int elemCnt = lowBoundary; elemCnt < highBoundary; elemCnt++)
            {
            noise += (*(fPixel+elemCnt) - sum) * (*(fPixel+elemCnt) - sum);
            }
          noise = sqrt(noise / numCropElements);
          }
        break;
      default:
        vtkErrorMacro("Could not get the data pointer.");
        return 0;
      }
    if ( refNode->IsA("vtkMRMLAstroVolumeNode") )
      {
      if(!strcmp(reader->GetHeaderValue("SlicerAstro.DATAMAX"), "0.") ||
             !strcmp(reader->GetHeaderValue("SlicerAstro.DATAMIN"), "0."))
        {
        volNode->SetAttribute("SlicerAstro.DATAMAX", DoubleToString(max).c_str());
        volNode->SetAttribute("SlicerAstro.DATAMIN", DoubleToString(min).c_str());
        }
      if (!strcmp(reader->GetHeaderValue("SlicerAstro.NOISE"), "0."))
        {
        volNode->SetAttribute("SlicerAstro.NOISE", DoubleToString(noise).c_str());
        }
      }
    else if ( refNode->IsA("vtkMRMLAstroLabelMapVolumeNode") )
      {
      if(!strcmp(reader->GetHeaderValue("SlicerAstro.DATAMAX"), "0.") ||
             !strcmp(reader->GetHeaderValue("SlicerAstro.DATAMIN"), "0."))
        {
        labvolNode->SetAttribute("SlicerAstro.DATAMAX", DoubleToString(max).c_str());
        labvolNode->SetAttribute("SlicerAstro.DATAMIN", DoubleToString(min).c_str());<commit_msg>calculation of noise only on negative part<commit_after>// MRML includes
#include "vtkMRMLAstroVolumeStorageNode.h"
#include "vtkMRMLScene.h"
#include "vtkMRMLVolumeNode.h"
#include "vtkMRMLAstroVolumeNode.h"
#include "vtkMRMLAstroVolumeDisplayNode.h"
#include "vtkMRMLAstroLabelMapVolumeNode.h"
#include "vtkMRMLAstroLabelMapVolumeDisplayNode.h"

//vtkFits includes
#include <vtkFITSReader.h>
#include <vtkFITSWriter.h>

// VTK includes
#include <vtkImageChangeInformation.h>
#include <vtkImageData.h>
#include <vtkNew.h>
#include <vtkObjectFactory.h>
#include <vtkStringArray.h>
#include <vtkVersion.h>
#include <vtkType.h>

//----------------------------------------------------------------------------
vtkMRMLNodeNewMacro(vtkMRMLAstroVolumeStorageNode);

//----------------------------------------------------------------------------
vtkMRMLAstroVolumeStorageNode::vtkMRMLAstroVolumeStorageNode()
{
  this->CenterImage = 0;
}

//----------------------------------------------------------------------------
vtkMRMLAstroVolumeStorageNode::~vtkMRMLAstroVolumeStorageNode()
{
}

namespace
{
//----------------------------------------------------------------------------
template <typename T> std::string NumberToString(T V)
{
  std::string stringValue;
  std::stringstream strstream;
  strstream << V;
  strstream >> stringValue;
  return stringValue;
}

//----------------------------------------------------------------------------
std::string DoubleToString(double Value)
{
  return NumberToString<double>(Value);
}
}//end namespace

//----------------------------------------------------------------------------
void vtkMRMLAstroVolumeStorageNode::WriteXML(ostream& of, int nIndent)
{
  Superclass::WriteXML(of, nIndent);
  vtkIndent indent(nIndent);

  std::stringstream ss;
  ss << this->CenterImage;
  of << indent << " centerImage=\"" << ss.str() << "\"";
}

//----------------------------------------------------------------------------
void vtkMRMLAstroVolumeStorageNode::ReadXMLAttributes(const char** atts)
{
  int disabledModify = this->StartModify();

  Superclass::ReadXMLAttributes(atts);

  const char* attName;
  const char* attValue;
  while (*atts != NULL)
    {
    attName = *(atts++);
    attValue = *(atts++);
    if (!strcmp(attName, "centerImage"))
      {
      std::stringstream ss;
      ss << attValue;
      ss >> this->CenterImage;
      }
    }

  this->EndModify(disabledModify);
}

//----------------------------------------------------------------------------
// Copy the node's attributes to this object.
// Does NOT copy: ID, FilePrefix, Name, StorageID
void vtkMRMLAstroVolumeStorageNode::Copy(vtkMRMLNode *anode)
{
  if (!anode)
    {
    return;
    }

  int disabledModify = this->StartModify();

  Superclass::Copy(anode);
  vtkMRMLAstroVolumeStorageNode *node = (vtkMRMLAstroVolumeStorageNode *) anode;

  this->SetCenterImage(node->CenterImage);

  this->EndModify(disabledModify);
}

//----------------------------------------------------------------------------
void vtkMRMLAstroVolumeStorageNode::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkMRMLStorageNode::PrintSelf(os,indent);
  os << indent << "CenterImage:   " << this->CenterImage << "\n";
}

//----------------------------------------------------------------------------
bool vtkMRMLAstroVolumeStorageNode::CanReadInReferenceNode(vtkMRMLNode *refNode)
{
  return refNode->IsA("vtkMRMLAstroVolumeNode") ||
         refNode->IsA("vtkMRMLAstroLabelMapVolumeNode");
}

//----------------------------------------------------------------------------
int vtkMRMLAstroVolumeStorageNode::ReadDataInternal(vtkMRMLNode *refNode)
{
  vtkMRMLAstroVolumeNode *volNode = NULL;
  vtkMRMLAstroLabelMapVolumeNode *labvolNode = NULL;
  vtkMRMLAstroVolumeDisplayNode *disNode = NULL;
  vtkMRMLAstroLabelMapVolumeDisplayNode *labdisNode = NULL;

  if ( refNode->IsA("vtkMRMLAstroVolumeNode") )
    {
    volNode = dynamic_cast <vtkMRMLAstroVolumeNode *> (refNode);
    disNode = volNode->GetAstroVolumeDisplayNode();
    }
  else if ( refNode->IsA("vtkMRMLAstroLabelMapVolumeNode") )
    {
    labvolNode = dynamic_cast <vtkMRMLAstroLabelMapVolumeNode *> (refNode);
    labdisNode = labvolNode->GetAstroLabelMapVolumeDisplayNode();
    }
  else
    {
    vtkErrorMacro(<< "Do not recognize node type " << refNode->GetClassName());
    return 0;
    }

  vtkNew<vtkFITSReader> reader;

  // Set Reader member variables
  if (this->CenterImage)
    {
    reader->SetUseNativeOriginOff();
    }
  else
    {
    reader->SetUseNativeOriginOn();
    }

  if ( refNode->IsA("vtkMRMLAstroVolumeNode") )
    {
    if (volNode->GetImageData())
      {
      volNode->SetAndObserveImageData (NULL);
      }
    }
  else if ( refNode->IsA("vtkMRMLAstroLabelMapVolumeNode") )
    {
    if (labvolNode->GetImageData())
      {
      labvolNode->SetAndObserveImageData (NULL);
      }
    }

  std::string fullName = this->GetFullNameFromFileName();

  if (fullName == std::string(""))
    {
    vtkErrorMacro("ReadData: File name not specified");
    return 0;
    }

  reader->SetFileName(fullName.c_str());

  // Check if this is a FITS file that we can read
  if (!reader->CanReadFile(fullName.c_str()))
    {
    vtkErrorMacro("ReadData: This is not a fits file");
    return 0;
    }

  // Read the header to see if the file corresponds to the MRML Node
  reader->UpdateInformation();

  if( refNode->IsA("vtkMRMLAstroVolumeNode") || refNode->IsA("vtkMRMLAstroLabelMapVolumeNode") )
    {
    if (reader->GetPointDataType() != vtkDataSetAttributes::SCALARS &&
         reader->GetNumberOfComponents() > 1 )
      {
      vtkErrorMacro("ReadData: MRMLVolumeNode does not match file kind");
      return 0;
      }
    }

  reader->Update();
  if ( refNode->IsA("vtkMRMLAstroVolumeNode") )
    {
    // set volume attributes
    vtkMatrix4x4* mat = reader->GetRasToIjkMatrix();
    volNode->SetRASToIJKMatrix(mat);

    //set WCSstruct
    volNode->SetWCSStruct(reader->GetWCSStruct());

    // parse WCS Status
    volNode->SetWCSStatus(reader->GetWCSStatus());

    // parse non-specific key-value pairs
    std::vector<std::string> keys = reader->GetHeaderKeysVector();
    for ( std::vector<std::string>::iterator kit = keys.begin();
          kit != keys.end(); ++kit)
      {
      volNode->SetAttribute((*kit).c_str(), reader->GetHeaderValue((*kit).c_str()));
      }

    // parse Space (WCS or IJK) to the display node
    if (disNode)
      {
      if (volNode->GetWCSStatus() != 0)
        {
        disNode->SetSpace("IJK");
        }
      if(!strcmp(reader->GetHeaderValue("SlicerAstro.CUNIT3"), "HZ") ||
         !strcmp(reader->GetHeaderValue("SlicerAstro.CUNIT3"), "Hz"))
        {
        disNode->SetSpaceQuantity(2,"frequency");
        }
      }
    if (!strcmp(reader->GetHeaderValue("SlicerAstro.BUNIT"), "W.U."))
      {
      volNode->SetAttribute("SlicerAstro.BUNIT", "JY/BEAM");
      vtkWarningMacro("The flux unit of Volume "<<volNode->GetName()<<
                      " is in Westerbork Unit. It will be automatically converted in JY/BEAM"<<endl);
      }
    }
  else if ( refNode->IsA("vtkMRMLAstroLabelMapVolumeNode") )
    {
    // set volume attributes
    vtkMatrix4x4* mat = reader->GetRasToIjkMatrix();
    labvolNode->SetRASToIJKMatrix(mat);
    //set WCSstruct
    labvolNode->SetWCSStruct(reader->GetWCSStruct());
    // parse WCS Status
    labvolNode->SetWCSStatus(reader->GetWCSStatus());
    // parse non-specific key-value pairs
    std::vector<std::string> keys = reader->GetHeaderKeysVector();
    for ( std::vector<std::string>::iterator kit = keys.begin();
          kit != keys.end(); ++kit)
      {
      labvolNode->SetAttribute((*kit).c_str(), reader->GetHeaderValue((*kit).c_str()));
      }
      // parse Space (WCS or IJK) to the display node
    if (labdisNode)
      {
      if (labvolNode->GetWCSStatus() != 0)
        {
        labdisNode->SetSpace("IJK");
        }
      if(!strcmp(reader->GetHeaderValue("SlicerAstro.CUNIT3"), "HZ") ||
         !strcmp(reader->GetHeaderValue("SlicerAstro.CUNIT3"), "Hz"))
        {
        labdisNode->SetSpaceQuantity(2,"frequency");
        }
      }
    if (!strcmp(reader->GetHeaderValue("SlicerAstro.BUNIT"), "W.U."))
      {
      labvolNode->SetAttribute("SlicerAstro.BUNIT", "JY/BEAM");
      vtkWarningMacro("The flux unit of Volume "<<labvolNode->GetName()<<
                      " is in Westerbork Unit. It will be automatically converted in JY/BEAM"<<endl);
      }
    }
  // rescaling flux and calculating max, min and noise
  if(!strcmp(reader->GetHeaderValue("SlicerAstro.DATAMAX"), "0.") ||
       !strcmp(reader->GetHeaderValue("SlicerAstro.DATAMIN"), "0.") ||
       !strcmp(reader->GetHeaderValue("SlicerAstro.BUNIT"), "W.U.") ||
       !strcmp(reader->GetHeaderValue("SlicerAstro.NOISE"), "0."))
    {
    vtkImageData *imageData = reader->GetOutput();
    int vtkType = reader->GetDataType();
    int *dims = imageData->GetDimensions();
    const int numComponents = imageData->GetNumberOfScalarComponents();
    double max = imageData->GetScalarTypeMin();
    double min = imageData->GetScalarTypeMax();
    double noise = 0.;
    const int numElements = dims[0] * dims[1] * dims[2] * numComponents;
    const int lowBoundary = dims[0] * dims[1] * 2;
    const int highBoundary = dims[0] * dims[1] * 4;
    switch (vtkType)
      {
      case VTK_DOUBLE:
        double *dPixel;
        dPixel = static_cast<double*>(imageData->GetScalarPointer(0,0,0));

        if (!strcmp(reader->GetHeaderValue("SlicerAstro.BUNIT"), "W.U."))
          {
          for( int elemCnt = 0; elemCnt < numElements; elemCnt++)
            {
            *(dPixel+elemCnt) *= 0.005;
            }
          }

        if(!strcmp(reader->GetHeaderValue("SlicerAstro.DATAMAX"), "0.") ||
             !strcmp(reader->GetHeaderValue("SlicerAstro.DATAMIN"), "0."))
          {
          for( int elemCnt = 0; elemCnt < numElements; elemCnt++ )
            {
            if(*(dPixel+elemCnt) > max)
              {
              max = *(dPixel+elemCnt);
              }
            if(*(dPixel+elemCnt) < min)
              {
              min = *(dPixel+elemCnt);
              }
            }
          }

        if (!strcmp(reader->GetHeaderValue("SlicerAstro.NOISE"), "0."))
          {
          double sum = 0.;
          int cont = 0;
          for( int elemCnt = lowBoundary; elemCnt < highBoundary; elemCnt++)
            {
            if(*(dPixel+elemCnt) < 0.)
              {
              sum += *(dPixel+elemCnt);
              cont++;
              }
            }
          sum /= cont;
          for( int elemCnt = lowBoundary; elemCnt < highBoundary; elemCnt++)
            {
            if(*(dPixel+elemCnt) < 0.)
              {
              noise += (*(dPixel+elemCnt) - sum) * (*(dPixel+elemCnt) - sum);
              }
            }
          noise = sqrt(noise / cont);
          }
        break;
      case VTK_FLOAT:
        float *fPixel;
        fPixel = static_cast<float*>(imageData->GetScalarPointer(0,0,0));
        if (!strcmp(reader->GetHeaderValue("SlicerAstro.BUNIT"), "W.U."))
          {
          for( int elemCnt = 0; elemCnt < numElements; elemCnt++)
            {
            *(fPixel+elemCnt) *= 0.005;
            }
          }

        if(!strcmp(reader->GetHeaderValue("SlicerAstro.DATAMAX"), "0.") ||
             !strcmp(reader->GetHeaderValue("SlicerAstro.DATAMIN"), "0."))
          {
          for( int elemCnt = 0; elemCnt < numElements; elemCnt++ )
            {
            if(*(fPixel+elemCnt) > max)
              {
              max = *(fPixel+elemCnt);
              }
            if(*(fPixel+elemCnt) < min)
              {
              min = *(fPixel+elemCnt);
              }
            }
          }

        if (!strcmp(reader->GetHeaderValue("SlicerAstro.NOISE"), "0."))
          {
          double sum = 0.;
          int cont = 0;
          for( int elemCnt = lowBoundary; elemCnt < highBoundary; elemCnt++)
            {
            if(*(fPixel+elemCnt) < 0.)
              {
              sum += *(fPixel+elemCnt);
              cont++;
              }
            }
          sum /= cont;
          for( int elemCnt = lowBoundary; elemCnt < highBoundary; elemCnt++)
            {
            if(*(fPixel+elemCnt) < 0.)
              {
              noise += (*(fPixel+elemCnt) - sum) * (*(fPixel+elemCnt) - sum);
              }
            }
          noise = sqrt(noise / cont);
          }
        break;
      default:
        vtkErrorMacro("Could not get the data pointer.");
        return 0;
      }
    if ( refNode->IsA("vtkMRMLAstroVolumeNode") )
      {
      if(!strcmp(reader->GetHeaderValue("SlicerAstro.DATAMAX"), "0.") ||
             !strcmp(reader->GetHeaderValue("SlicerAstro.DATAMIN"), "0."))
        {
        volNode->SetAttribute("SlicerAstro.DATAMAX", DoubleToString(max).c_str());
        volNode->SetAttribute("SlicerAstro.DATAMIN", DoubleToString(min).c_str());
        }
      if (!strcmp(reader->GetHeaderValue("SlicerAstro.NOISE"), "0."))
        {
        volNode->SetAttribute("SlicerAstro.NOISE", DoubleToString(noise).c_str());
        }
      }
    else if ( refNode->IsA("vtkMRMLAstroLabelMapVolumeNode") )
      {
      if(!strcmp(reader->GetHeaderValue("SlicerAstro.DATAMAX"), "0.") ||
             !strcmp(reader->GetHeaderValue("SlicerAstro.DATAMIN"), "0."))
        {
        labvolNode->SetAttribute("SlicerAstro.DATAMAX", DoubleToString(max).c_str());
        labvolNode->SetAttribute("SlicerAstro.DATAMIN", DoubleToString(min).c_str());
{'fraction_non_alphanumeric': 0.19968594608741166, 'fraction_numerical': 0.004935132912102292, 'mean_word_length': 2.1733301696523903, 'pattern_counts': {'":': 0, '<': 143, '<?xml version=': 0, '>': 263, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '3221973', 'n_tokens_mistral': 8644, 'n_tokens_neox': 8412, 'n_words': 1386}