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

  Program:   Visualization Toolkit
  Module:    vtkFillHolesFilter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkFillHolesFilter.h"

#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkDoubleArray.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkTriangleStrip.h"
#include "vtkPolygon.h"
#include "vtkSphere.h"
#include "vtkMath.h"

vtkCxxRevisionMacro(vtkFillHolesFilter, "1.1");
vtkStandardNewMacro(vtkFillHolesFilter);

//------------------------------------------------------------------------
vtkFillHolesFilter::vtkFillHolesFilter()
{
  this->HoleSize = 1.0;
}

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

//------------------------------------------------------------------------
int vtkFillHolesFilter::RequestData(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
{
  // get the info objects
  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  // get the input and ouptut
  vtkPolyData *input = vtkPolyData::SafeDownCast(
    inInfo->Get(vtkDataObject::DATA_OBJECT()));
  vtkPolyData *output = vtkPolyData::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));

  vtkPointData *pd=input->GetPointData(), *outPD=output->GetPointData();

  vtkDebugMacro(<<"Executing hole fill operation");

  // check the input, build data structures as necessary
  vtkIdType numPts, npts, *pts;
  vtkPoints *inPts=input->GetPoints();
  vtkIdType numPolys = input->GetNumberOfPolys();
  vtkIdType numStrips = input->GetNumberOfStrips();
  if ( (numPts=input->GetNumberOfPoints()) < 1 || !inPts ||
       (numPolys < 1 && numStrips < 1) )
    {
    vtkDebugMacro(<<"No input data!");
    return 1;
    }

  vtkPolyData *Mesh = vtkPolyData::New();
  Mesh->SetPoints(inPts);
  vtkCellArray *newPolys, *inPolys=input->GetPolys(), *inStrips=input->GetStrips();
  if ( numStrips > 0 )
    {
    newPolys = vtkCellArray::New();
    if ( numPolys > 0 )
      {
      newPolys->DeepCopy(inPolys);
      }
    else
      {
      newPolys->Allocate(newPolys->EstimateSize(numStrips,5));
      }
    inStrips = input->GetStrips();
    for ( inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); )
      {
      vtkTriangleStrip::DecomposeStrip(npts, pts, newPolys);
      }
    Mesh->SetPolys(newPolys);
    newPolys->Delete();
    }
  else
    {
    newPolys = inPolys;
    Mesh->SetPolys(newPolys);
    }
  Mesh->BuildLinks();

  // Allocate storage for lines/points (arbitrary allocation sizes)
  //
  vtkPolyData *Lines = vtkPolyData::New();
  vtkCellArray *newLines = vtkCellArray::New();
  newLines->Allocate(numPts/10);
  Lines->SetLines(newLines);
  Lines->SetPoints(inPts);

  // grab all free edges and place them into a temporary polydata
  int abort=0;
  vtkIdType cellId, p1, p2, numNei, i, newId, numCells=newPolys->GetNumberOfCells();
  vtkIdType progressInterval=numCells/20+1;
  vtkIdList *neighbors = vtkIdList::New();
  neighbors->Allocate(VTK_CELL_SIZE);
  for (cellId=0, newPolys->InitTraversal();
       newPolys->GetNextCell(npts,pts) && !abort; cellId++)
    {
    if ( ! (cellId % progressInterval) ) //manage progress / early abort
      {
      this->UpdateProgress ((double)cellId / numCells);
      abort = this->GetAbortExecute();
      }

    for (i=0; i < npts; i++)
      {
      p1 = pts[i];
      p2 = pts[(i+1)%npts];

      Mesh->GetCellEdgeNeighbors(cellId,p1,p2, neighbors);
      numNei = neighbors->GetNumberOfIds();

      if ( numNei < 1 )
        {
        newId = newLines->InsertNextCell(2);
        newLines->InsertCellPoint(p1);
        newLines->InsertCellPoint(p2);
        }
      }
    }

  // Track all free edges and see whether polygons can be built from them.
  // For each polygon of appropriate HoleSize, triangulate the hole and
  // add to the output list of cells
  vtkIdType numHolesFilled=0;
  numCells = newLines->GetNumberOfCells();
  vtkCellArray *newCells = NULL;
  if ( numCells > 3 ) //only do the work if there are free edges
    {
    double sphere[4];
    vtkIdType startId, neiId, currentCellId, hints[2]; hints[0]=0; hints[1]=0;
    vtkPolygon *polygon=vtkPolygon::New();
    polygon->Points->SetDataTypeToDouble();
    vtkIdList *endId = vtkIdList::New();
    endId->SetNumberOfIds(1);
    char *visited = new char [numCells];
    memset(visited, 0, numCells);
    Lines->BuildLinks(); //build the neighbor data structure
    newCells = vtkCellArray::New();
    newCells->DeepCopy(inPolys);

    for (cellId=0; cellId < numCells && !abort; cellId++)
      {
      if ( ! visited[cellId] )
        {
        visited[cellId] = 1;
        // Setup the polygon
        Lines->GetCellPoints(cellId, npts, pts);
        startId = pts[0];
        polygon->PointIds->Reset();
        polygon->Points->Reset();
        polygon->PointIds->InsertId(0,pts[0]);
        polygon->Points->InsertPoint(0,inPts->GetPoint(pts[0]));

        // Work around the loop and terminate when the loop ends
        endId->SetId(0,pts[1]);
        int valid = 1;
        currentCellId = cellId;
        while ( startId != endId->GetId(0) && valid )
          {
          polygon->PointIds->InsertNextId(endId->GetId(0));
          polygon->Points->InsertNextPoint(inPts->GetPoint(endId->GetId(0)));
          Lines->GetCellNeighbors(currentCellId,endId,neighbors);
          if ( neighbors->GetNumberOfIds() == 0 )
            {
            valid = 0;
            }
          else if ( neighbors->GetNumberOfIds() > 1 )
            {
            //have to logically split this vertex
            valid = 0;
            }
          else
            {
            neiId = neighbors->GetId(0);
            visited[neiId] = 1;
            Lines->GetCellPoints(neiId,npts,pts);
            endId->SetId( 0, (pts[0] != endId->GetId(0) ? pts[0] : pts[1] ) );
            currentCellId = neiId;
            }
          }//while loop connected

        // Evaluate the size of the loop and see if it is small enough
        if ( valid )
          {
          vtkSphere::ComputeBoundingSphere(static_cast<vtkDoubleArray*>(polygon->Points->GetData())->GetPointer(0),
                                           polygon->PointIds->GetNumberOfIds(),sphere,hints);
          if ( sphere[3] <= this->HoleSize )
            {
            // Now triangulate the loop and pass to the output
            numHolesFilled++;
            polygon->NonDegenerateTriangulate(neighbors);
            for ( i=0; i < neighbors->GetNumberOfIds(); i+=3 )
              {
              newCells->InsertNextCell(3);
              newCells->InsertCellPoint(polygon->PointIds->GetId(neighbors->GetId(i)));
              newCells->InsertCellPoint(polygon->PointIds->GetId(neighbors->GetId(i+1)));
              newCells->InsertCellPoint(polygon->PointIds->GetId(neighbors->GetId(i+2)));
              }
            }//if hole small enough
          }//if a valid loop
        }//if not yet visited a line
      }//for all lines
    polygon->Delete();
    endId->Delete();
    delete [] visited;
    }//if loops present in the input

  // Clean up
  neighbors->Delete();
  Lines->Delete();

  // No new points are created, so the points and point data can be passed
  // through to the output.
  output->SetPoints(inPts);
  outPD->PassData(pd);

  // New cells are created, so currently we do not pass the cell data.
  // It would be pretty easy to extend the existing cell data and mark
  // the new cells with special data values.
  output->SetVerts(input->GetVerts());
  output->SetLines(input->GetLines());
  if ( newCells )
    {
    output->SetPolys(newCells);
    newCells->Delete();
    }
  output->SetStrips(input->GetStrips());

  Mesh->Delete();
  newLines->Delete();
  return 1;
}

//------------------------------------------------------------------------
void vtkFillHolesFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Hole Size: " << this->HoleSize << "\n";
}
<commit_msg>ENH:Removed warning unused variable<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkFillHolesFilter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkFillHolesFilter.h"

#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkDoubleArray.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkTriangleStrip.h"
#include "vtkPolygon.h"
#include "vtkSphere.h"
#include "vtkMath.h"

vtkCxxRevisionMacro(vtkFillHolesFilter, "1.2");
vtkStandardNewMacro(vtkFillHolesFilter);

//------------------------------------------------------------------------
vtkFillHolesFilter::vtkFillHolesFilter()
{
  this->HoleSize = 1.0;
}

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

//------------------------------------------------------------------------
int vtkFillHolesFilter::RequestData(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
{
  // get the info objects
  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  // get the input and ouptut
  vtkPolyData *input = vtkPolyData::SafeDownCast(
    inInfo->Get(vtkDataObject::DATA_OBJECT()));
  vtkPolyData *output = vtkPolyData::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));

  vtkPointData *pd=input->GetPointData(), *outPD=output->GetPointData();

  vtkDebugMacro(<<"Executing hole fill operation");

  // check the input, build data structures as necessary
  vtkIdType numPts, npts, *pts;
  vtkPoints *inPts=input->GetPoints();
  vtkIdType numPolys = input->GetNumberOfPolys();
  vtkIdType numStrips = input->GetNumberOfStrips();
  if ( (numPts=input->GetNumberOfPoints()) < 1 || !inPts ||
       (numPolys < 1 && numStrips < 1) )
    {
    vtkDebugMacro(<<"No input data!");
    return 1;
    }

  vtkPolyData *Mesh = vtkPolyData::New();
  Mesh->SetPoints(inPts);
  vtkCellArray *newPolys, *inPolys=input->GetPolys(), *inStrips=input->GetStrips();
  if ( numStrips > 0 )
    {
    newPolys = vtkCellArray::New();
    if ( numPolys > 0 )
      {
      newPolys->DeepCopy(inPolys);
      }
    else
      {
      newPolys->Allocate(newPolys->EstimateSize(numStrips,5));
      }
    inStrips = input->GetStrips();
    for ( inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); )
      {
      vtkTriangleStrip::DecomposeStrip(npts, pts, newPolys);
      }
    Mesh->SetPolys(newPolys);
    newPolys->Delete();
    }
  else
    {
    newPolys = inPolys;
    Mesh->SetPolys(newPolys);
    }
  Mesh->BuildLinks();

  // Allocate storage for lines/points (arbitrary allocation sizes)
  //
  vtkPolyData *Lines = vtkPolyData::New();
  vtkCellArray *newLines = vtkCellArray::New();
  newLines->Allocate(numPts/10);
  Lines->SetLines(newLines);
  Lines->SetPoints(inPts);

  // grab all free edges and place them into a temporary polydata
  int abort=0;
  vtkIdType cellId, p1, p2, numNei, i, numCells=newPolys->GetNumberOfCells();
  vtkIdType progressInterval=numCells/20+1;
  vtkIdList *neighbors = vtkIdList::New();
  neighbors->Allocate(VTK_CELL_SIZE);
  for (cellId=0, newPolys->InitTraversal();
       newPolys->GetNextCell(npts,pts) && !abort; cellId++)
    {
    if ( ! (cellId % progressInterval) ) //manage progress / early abort
      {
      this->UpdateProgress ((double)cellId / numCells);
      abort = this->GetAbortExecute();
      }

    for (i=0; i < npts; i++)
      {
      p1 = pts[i];
      p2 = pts[(i+1)%npts];

      Mesh->GetCellEdgeNeighbors(cellId,p1,p2, neighbors);
      numNei = neighbors->GetNumberOfIds();

      if ( numNei < 1 )
        {
        newLines->InsertNextCell(2);
        newLines->InsertCellPoint(p1);
        newLines->InsertCellPoint(p2);
        }
      }
    }

  // Track all free edges and see whether polygons can be built from them.
  // For each polygon of appropriate HoleSize, triangulate the hole and
  // add to the output list of cells
  vtkIdType numHolesFilled=0;
  numCells = newLines->GetNumberOfCells();
  vtkCellArray *newCells = NULL;
  if ( numCells > 3 ) //only do the work if there are free edges
    {
    double sphere[4];
    vtkIdType startId, neiId, currentCellId, hints[2]; hints[0]=0; hints[1]=0;
    vtkPolygon *polygon=vtkPolygon::New();
    polygon->Points->SetDataTypeToDouble();
    vtkIdList *endId = vtkIdList::New();
    endId->SetNumberOfIds(1);
    char *visited = new char [numCells];
    memset(visited, 0, numCells);
    Lines->BuildLinks(); //build the neighbor data structure
    newCells = vtkCellArray::New();
    newCells->DeepCopy(inPolys);

    for (cellId=0; cellId < numCells && !abort; cellId++)
      {
      if ( ! visited[cellId] )
        {
        visited[cellId] = 1;
        // Setup the polygon
        Lines->GetCellPoints(cellId, npts, pts);
        startId = pts[0];
        polygon->PointIds->Reset();
        polygon->Points->Reset();
        polygon->PointIds->InsertId(0,pts[0]);
        polygon->Points->InsertPoint(0,inPts->GetPoint(pts[0]));

        // Work around the loop and terminate when the loop ends
        endId->SetId(0,pts[1]);
        int valid = 1;
        currentCellId = cellId;
        while ( startId != endId->GetId(0) && valid )
          {
          polygon->PointIds->InsertNextId(endId->GetId(0));
          polygon->Points->InsertNextPoint(inPts->GetPoint(endId->GetId(0)));
          Lines->GetCellNeighbors(currentCellId,endId,neighbors);
          if ( neighbors->GetNumberOfIds() == 0 )
            {
            valid = 0;
            }
          else if ( neighbors->GetNumberOfIds() > 1 )
            {
            //have to logically split this vertex
            valid = 0;
            }
          else
            {
            neiId = neighbors->GetId(0);
            visited[neiId] = 1;
            Lines->GetCellPoints(neiId,npts,pts);
            endId->SetId( 0, (pts[0] != endId->GetId(0) ? pts[0] : pts[1] ) );
            currentCellId = neiId;
            }
          }//while loop connected

        // Evaluate the size of the loop and see if it is small enough
        if ( valid )
          {
          vtkSphere::ComputeBoundingSphere(static_cast<vtkDoubleArray*>(polygon->Points->GetData())->GetPointer(0),
                                           polygon->PointIds->GetNumberOfIds(),sphere,hints);
          if ( sphere[3] <= this->HoleSize )
            {
            // Now triangulate the loop and pass to the output
            numHolesFilled++;
            polygon->NonDegenerateTriangulate(neighbors);
            for ( i=0; i < neighbors->GetNumberOfIds(); i+=3 )
              {
              newCells->InsertNextCell(3);
              newCells->InsertCellPoint(polygon->PointIds->GetId(neighbors->GetId(i)));
              newCells->InsertCellPoint(polygon->PointIds->GetId(neighbors->GetId(i+1)));
              newCells->InsertCellPoint(polygon->PointIds->GetId(neighbors->GetId(i+2)));
              }
            }//if hole small enough
          }//if a valid loop
        }//if not yet visited a line
      }//for all lines
    polygon->Delete();
    endId->Delete();
    delete [] visited;
    }//if loops present in the input

  // Clean up
  neighbors->Delete();
  Lines->Delete();

  // No new points are created, so the points and point data can be passed
  // through to the output.
  output->SetPoints(inPts);
  outPD->PassData(pd);

  // New cells are created, so currently we do not pass the cell data.
  // It would be pretty easy to extend the existing cell data and mark
  // the new cells with special data values.
  output->SetVerts(input->GetVerts());
  output->SetLines(input->GetLines());
  if ( newCells )
    {
    output->SetPolys(newCells);
    newCells->Delete();
    }
  output->SetStrips(input->GetStrips());

  Mesh->Delete();
  newLines->Delete();
  return 1;
}

//------------------------------------------------------------------------
void vtkFillHolesFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Hole Size: " << this->HoleSize << "\n";
}
<|endoftext|>


<commit_before>#include "zmq.h"
#include <iostream>
#include "AliHLTDataTypes.h"
#include "AliHLTComponent.h"
#include "AliHLTMessage.h"
#include "TClass.h"
#include "TCanvas.h"
#include "TMap.h"
#include "TPRegexp.h"
#include "TObjString.h"
#include "TDirectory.h"
#include "TList.h"
#include "AliZMQhelpers.h"
#include "TMessage.h"
#include "TSystem.h"
#include "TApplication.h"
#include "TH1.h"
#include "TH1F.h"
#include <time.h>
#include <string>
#include <map>
#include "TFile.h"
#include "TSystem.h"
#include "signal.h"
class MySignalHandler;

//this is meant to become a class, hence the structure with global vars etc.
//Also the code is rather flat - it is a bit of a playground to test ideas.
//TODO structure this at some point, e.g. introduce a SIMPLE unified way of handling
//zmq payloads, maybe a AliZMQmessage class which would by default be multipart and provide
//easy access to payloads based on topic or so (a la HLT GetFirstInputObject() etc...)

//methods
int ProcessOptionString(TString arguments);
int UpdatePad(TObject*);
int DumpToFile(TObject* object);
void* run(void* arg);

//configuration vars
Bool_t fVerbose = kFALSE;
TString fZMQconfigIN  = "PULL>tcp://localhost:60211";
int fZMQsocketModeIN=-1;
TString fZMQsubscriptionIN = "";
TString fFilter = "";

TString fFileName="";
TFile* fFile=NULL;

int fPollInterval = 0;
int fPollTimeout = 1000; //1s

//internal state
void* fZMQcontext = NULL;             //ze zmq context
void* fZMQin  = NULL;                 //the in socket - entry point for the data to be merged.

TApplication* gApp;
TCanvas* fCanvas;
TObjArray fDrawables;

TPRegexp* fSelectionRegexp = NULL;
TPRegexp* fUnSelectionRegexp = NULL;
TString fDrawOptions;
Bool_t fScaleLogX = kFALSE;
Bool_t fScaleLogY = kFALSE;
Bool_t fScaleLogZ = kFALSE;
Bool_t fResetOnRequest = kFALSE;

ULong64_t iterations=0;

const char* fUSAGE =
    "ZMQhstViewer: Draw() all ROOT drawables in a message\n"
    "options: \n"
    " -in : data in\n"
    " -sleep : how long to sleep in between requests for data in s (if applicable)\n"
    " -timeout : how long to wait for the server to reply (s)\n"
    " -Verbose : be verbose\n"
    " -select : only show selected histograms (by regexp)\n"
    " -unselect : as select, only inverted\n"
    " -drawoptions : what draw option to use\n"
    " -file : dump input to file and exit\n"
    " log[xyz] : use log scale on [xyz] dimension\n"
    ;
//_______________________________________________________________________________________
class MySignalHandler : public TSignalHandler
{
  public:
	MySignalHandler(ESignals sig) : TSignalHandler(sig) {}
	Bool_t Notify()
	{
    Printf("signal received, exiting");
		fgTerminationSignaled = true;
		return TSignalHandler::Notify();
	}
	static bool TerminationSignaled() { return fgTerminationSignaled; }
	static bool fgTerminationSignaled;
};
bool MySignalHandler::fgTerminationSignaled = false;

void sig_handler(int signo)
{
  if (signo == SIGINT)
    printf("received SIGINT\n");
  MySignalHandler::fgTerminationSignaled=true;
}

//_______________________________________________________________________________________
void* run(void* arg)
{
  //main loop
  while(!MySignalHandler::TerminationSignaled())
  {
    errno=0;
    //send a request if we are using REQ
    if (fZMQsocketModeIN==ZMQ_REQ)
    {
      TString request;
      TString requestTopic;

      if (fSelectionRegexp || fUnSelectionRegexp)
      {
        requestTopic = "CONFIG";
        if (fSelectionRegexp) request += " select="+fSelectionRegexp->GetPattern();
        if (fUnSelectionRegexp) request += " unselect="+fUnSelectionRegexp->GetPattern();
        if (fResetOnRequest) request += " ResetOnRequest";
        zmq_send(fZMQin, requestTopic.Data(), requestTopic.Length(), ZMQ_SNDMORE);
        zmq_send(fZMQin, request.Data(), request.Length(), ZMQ_SNDMORE);
      }

      if (fVerbose) Printf("sending request %s %s",requestTopic.Data(), request.Data());
      zmq_send(fZMQin, "", 0, ZMQ_SNDMORE);
      zmq_send(fZMQin, "", 0, 0);
    }

    //wait for the data
    zmq_pollitem_t sockets[] = {
                                 { fZMQin, 0, ZMQ_POLLIN, 0 },
                               };
    int rc = zmq_poll(sockets, 1, (fZMQsocketModeIN==ZMQ_REQ)?fPollTimeout:-1);

    if (rc==-1 && errno==ETERM)
    {
      Printf("jumping out of main loop");
      break;
    }

    if (!(sockets[0].revents & ZMQ_POLLIN))
    {
      //server died
      Printf("connection timed out, server %s died?", fZMQconfigIN.Data());
      fZMQsocketModeIN = alizmq_socket_init(fZMQin, fZMQcontext, fZMQconfigIN.Data());
      if (fZMQsocketModeIN < 0) return NULL;
      continue;
    }
    else
    {
      //get all data (topic+body), possibly many of them
      aliZMQmsg message;
      alizmq_msg_recv(&message, fZMQin, 0);
      for (aliZMQmsg::iterator i=message.begin(); i!=message.end(); ++i)
      {
        TObject* object;
        alizmq_msg_iter_data(i, object);
        if (object) UpdatePad(object);

        if (!fFileName.IsNull())
        {
          DumpToFile(object);
        }
      }
      alizmq_msg_close(&message);

    }//socket 0
    gSystem->ProcessEvents();
    usleep(fPollInterval);
  }//main loop
  return NULL;
}

//_______________________________________________________________________________________
int main(int argc, char** argv)
{
  //process args
  int noptions = ProcessOptionString(AliOptionParser::GetFullArgString(argc,argv));
  if (noptions<=0)
  {
    printf("%s",fUSAGE);
    return 1;
  }

  TH1::AddDirectory(kFALSE);
  TDirectory::AddDirectory(kFALSE);
  gApp = new TApplication("viewer", &argc, argv);
  gApp->SetReturnFromRun(true);
  //gApp->Run();

  fCanvas = new TCanvas();
  gSystem->ProcessEvents();

  int mainReturnCode=0;

  //init stuff
  //globally enable schema evolution for serializing ROOT objects
  TMessage::EnableSchemaEvolutionForAll(kTRUE);
  //ZMQ init
  fZMQcontext = zmq_ctx_new();
  fZMQsocketModeIN = alizmq_socket_init(fZMQin, fZMQcontext, fZMQconfigIN.Data(), -1, 2);
  if (fZMQsocketModeIN < 0) return 1;

  gSystem->ResetSignal(kSigPipe);
  gSystem->ResetSignal(kSigQuit);
  gSystem->ResetSignal(kSigInterrupt);
  gSystem->ResetSignal(kSigTermination);
  //gSystem->AddSignalHandler(new MySignalHandler(kSigPipe));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigQuit));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigInterrupt));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigTermination));

  if (signal(SIGINT, sig_handler) == SIG_ERR)
  printf("\ncan't catch SIGINT\n");

  run(NULL);

  Printf("exiting...");
  if (fFile) fFile->Close();
  delete fFile; fFile=0;

  //destroy ZMQ sockets

  int linger=0;
  zmq_setsockopt(fZMQin, ZMQ_LINGER, &linger, sizeof(linger));
  zmq_close(fZMQin);
  zmq_ctx_term(fZMQcontext);
  return mainReturnCode;
}

//______________________________________________________________________________
int DumpToFile(TObject* object)
{
  Option_t* fileMode="RECREATE";
  if (!fFile) fFile = new TFile(fFileName,fileMode);
  if (fVerbose) Printf("writing object %s to %s",object->GetName(), fFileName.Data());
  int rc = object->Write(object->GetName(),TObject::kOverwrite);
  MySignalHandler::fgTerminationSignaled=true;
  return rc;
}

//______________________________________________________________________________
int UpdatePad(TObject* object)
{
  if (!object) return -1;
  const char* name = object->GetName();

  TObject* drawable = fDrawables.FindObject(name);
  int padIndex = fDrawables.IndexOf(drawable);

  if (fVerbose) Printf("in: %s", name);
  Bool_t selected = kTRUE;
  Bool_t unselected = kFALSE;
  if (fSelectionRegexp) selected = fSelectionRegexp->Match(name);
  if (fUnSelectionRegexp) unselected = fUnSelectionRegexp->Match(name);
  if (!selected || unselected) return 0;

  if (drawable)
  {
    //only redraw the one thing
    if (fVerbose) Printf("  redrawing %s in pad %i", name, padIndex);
    fCanvas->cd(padIndex+1);
    gPad->GetListOfPrimitives()->Remove(drawable);
    gPad->Clear();
    fDrawables.RemoveAt(padIndex);
    delete drawable;
    fDrawables.AddAt(object, padIndex);
    object->Draw(fDrawOptions);
    gPad->Modified(kTRUE);
  }
  else
  {
    if (fVerbose) Printf("  new object %s", name);
    //add the new object to the collection, restructure the canvas
    //and redraw everything
    fDrawables.AddLast(object);

    //after we clear the canvas, the pads are gone, clear the pad cache as well
    fCanvas->Clear();
    fCanvas->DivideSquare(fDrawables.GetLast()+1);

    //redraw all objects at their old places and the new one as last
    for (int i=0; i<fDrawables.GetLast()+1; i++)
    {
      TObject* obj = fDrawables[i];
      fCanvas->cd(i+1);
      if (fScaleLogX) gPad->SetLogx();
      if (fScaleLogY) gPad->SetLogy();
      if (fScaleLogZ) gPad->SetLogz();
      if (fVerbose) Printf("  drawing %s in pad %i", obj->GetName(), i);
      if (obj) obj->Draw();
    }
  }
  gSystem->ProcessEvents();
  fCanvas->Update();
  return 0;
}

//______________________________________________________________________________
int ProcessOptionString(TString arguments)
{
  //process passed options
  stringMap* options = AliOptionParser::TokenizeOptionString(arguments);
  int nOptions = 0;
  for (stringMap::iterator i=options->begin(); i!=options->end(); ++i)
  {
    //Printf("  %s : %s", i->first.data(), i->second.data());
    const TString& option = i->first;
    const TString& value = i->second;
    if (option.EqualTo("PollInterval") || option.EqualTo("sleep"))
    {
      fPollInterval = round(value.Atof()*1e6);
    }
    else if (option.EqualTo("PollTimeout") || option.EqualTo("timeout"))
    {
      fPollTimeout = round(value.Atof()*1e3);
    }
    else if (option.EqualTo("ZMQconfigIN") || option.EqualTo("in") )
    {
      fZMQconfigIN = value;
    }
    else if (option.EqualTo("Verbose"))
    {
      fVerbose=kTRUE;
    }
    else if (option.EqualTo("select"))
    {
      delete fSelectionRegexp;
      fSelectionRegexp=new TPRegexp(value);
    }
    else if (option.EqualTo("unselect"))
    {
      delete fUnSelectionRegexp;
      fUnSelectionRegexp=new TPRegexp(value);
    }
    else if (option.EqualTo("ResetOnRequest"))
    {
      fResetOnRequest = kTRUE;
    }
    else if (option.EqualTo("drawoptions"))
    {
      fDrawOptions = value;
    }
    else if (option.EqualTo("logx"))
    {
      fScaleLogX=kTRUE;
    }
    else if (option.EqualTo("logy"))
    {
      fScaleLogY=kTRUE;
    }
    else if (option.EqualTo("logy"))
    {
      fScaleLogY=kTRUE;
    }
    else if (option.EqualTo("file"))
    {
      fFileName = value;
    }
    else
    {
      nOptions=-1;
      break;
    }
    nOptions++;
  }
  delete options; //tidy up

  return nOptions;
}

<commit_msg>fix logz<commit_after>#include "zmq.h"
#include <iostream>
#include "AliHLTDataTypes.h"
#include "AliHLTComponent.h"
#include "AliHLTMessage.h"
#include "TClass.h"
#include "TCanvas.h"
#include "TMap.h"
#include "TPRegexp.h"
#include "TObjString.h"
#include "TDirectory.h"
#include "TList.h"
#include "AliZMQhelpers.h"
#include "TMessage.h"
#include "TSystem.h"
#include "TApplication.h"
#include "TH1.h"
#include "TH1F.h"
#include <time.h>
#include <string>
#include <map>
#include "TFile.h"
#include "TSystem.h"
#include "signal.h"
class MySignalHandler;

//this is meant to become a class, hence the structure with global vars etc.
//Also the code is rather flat - it is a bit of a playground to test ideas.
//TODO structure this at some point, e.g. introduce a SIMPLE unified way of handling
//zmq payloads, maybe a AliZMQmessage class which would by default be multipart and provide
//easy access to payloads based on topic or so (a la HLT GetFirstInputObject() etc...)

//methods
int ProcessOptionString(TString arguments);
int UpdatePad(TObject*);
int DumpToFile(TObject* object);
void* run(void* arg);

//configuration vars
Bool_t fVerbose = kFALSE;
TString fZMQconfigIN  = "PULL>tcp://localhost:60211";
int fZMQsocketModeIN=-1;
TString fZMQsubscriptionIN = "";
TString fFilter = "";

TString fFileName="";
TFile* fFile=NULL;

int fPollInterval = 0;
int fPollTimeout = 1000; //1s

//internal state
void* fZMQcontext = NULL;             //ze zmq context
void* fZMQin  = NULL;                 //the in socket - entry point for the data to be merged.

TApplication* gApp;
TCanvas* fCanvas;
TObjArray fDrawables;

TPRegexp* fSelectionRegexp = NULL;
TPRegexp* fUnSelectionRegexp = NULL;
TString fDrawOptions;
Bool_t fScaleLogX = kFALSE;
Bool_t fScaleLogY = kFALSE;
Bool_t fScaleLogZ = kFALSE;
Bool_t fResetOnRequest = kFALSE;

ULong64_t iterations=0;

const char* fUSAGE =
    "ZMQhstViewer: Draw() all ROOT drawables in a message\n"
    "options: \n"
    " -in : data in\n"
    " -sleep : how long to sleep in between requests for data in s (if applicable)\n"
    " -timeout : how long to wait for the server to reply (s)\n"
    " -Verbose : be verbose\n"
    " -select : only show selected histograms (by regexp)\n"
    " -unselect : as select, only inverted\n"
    " -drawoptions : what draw option to use\n"
    " -file : dump input to file and exit\n"
    " -log[xyz] : use log scale on [xyz] dimension\n"
    ;
//_______________________________________________________________________________________
class MySignalHandler : public TSignalHandler
{
  public:
	MySignalHandler(ESignals sig) : TSignalHandler(sig) {}
	Bool_t Notify()
	{
    Printf("signal received, exiting");
		fgTerminationSignaled = true;
		return TSignalHandler::Notify();
	}
	static bool TerminationSignaled() { return fgTerminationSignaled; }
	static bool fgTerminationSignaled;
};
bool MySignalHandler::fgTerminationSignaled = false;

void sig_handler(int signo)
{
  if (signo == SIGINT)
    printf("received SIGINT\n");
  MySignalHandler::fgTerminationSignaled=true;
}

//_______________________________________________________________________________________
void* run(void* arg)
{
  //main loop
  while(!MySignalHandler::TerminationSignaled())
  {
    errno=0;
    //send a request if we are using REQ
    if (fZMQsocketModeIN==ZMQ_REQ)
    {
      TString request;
      TString requestTopic;

      if (fSelectionRegexp || fUnSelectionRegexp)
      {
        requestTopic = "CONFIG";
        if (fSelectionRegexp) request += " select="+fSelectionRegexp->GetPattern();
        if (fUnSelectionRegexp) request += " unselect="+fUnSelectionRegexp->GetPattern();
        if (fResetOnRequest) request += " ResetOnRequest";
        zmq_send(fZMQin, requestTopic.Data(), requestTopic.Length(), ZMQ_SNDMORE);
        zmq_send(fZMQin, request.Data(), request.Length(), ZMQ_SNDMORE);
      }

      if (fVerbose) Printf("sending request %s %s",requestTopic.Data(), request.Data());
      zmq_send(fZMQin, "", 0, ZMQ_SNDMORE);
      zmq_send(fZMQin, "", 0, 0);
    }

    //wait for the data
    zmq_pollitem_t sockets[] = {
                                 { fZMQin, 0, ZMQ_POLLIN, 0 },
                               };
    int rc = zmq_poll(sockets, 1, (fZMQsocketModeIN==ZMQ_REQ)?fPollTimeout:-1);

    if (rc==-1 && errno==ETERM)
    {
      Printf("jumping out of main loop");
      break;
    }

    if (!(sockets[0].revents & ZMQ_POLLIN))
    {
      //server died
      Printf("connection timed out, server %s died?", fZMQconfigIN.Data());
      fZMQsocketModeIN = alizmq_socket_init(fZMQin, fZMQcontext, fZMQconfigIN.Data());
      if (fZMQsocketModeIN < 0) return NULL;
      continue;
    }
    else
    {
      //get all data (topic+body), possibly many of them
      aliZMQmsg message;
      alizmq_msg_recv(&message, fZMQin, 0);
      for (aliZMQmsg::iterator i=message.begin(); i!=message.end(); ++i)
      {
        TObject* object;
        alizmq_msg_iter_data(i, object);
        if (object) UpdatePad(object);

        if (!fFileName.IsNull())
        {
          DumpToFile(object);
        }
      }
      alizmq_msg_close(&message);

    }//socket 0
    gSystem->ProcessEvents();
    usleep(fPollInterval);
  }//main loop
  return NULL;
}

//_______________________________________________________________________________________
int main(int argc, char** argv)
{
  //process args
  int noptions = ProcessOptionString(AliOptionParser::GetFullArgString(argc,argv));
  if (noptions<=0)
  {
    printf("%s",fUSAGE);
    return 1;
  }

  TH1::AddDirectory(kFALSE);
  TDirectory::AddDirectory(kFALSE);
  gApp = new TApplication("viewer", &argc, argv);
  gApp->SetReturnFromRun(true);
  //gApp->Run();

  fCanvas = new TCanvas();
  gSystem->ProcessEvents();

  int mainReturnCode=0;

  //init stuff
  //globally enable schema evolution for serializing ROOT objects
  TMessage::EnableSchemaEvolutionForAll(kTRUE);
  //ZMQ init
  fZMQcontext = zmq_ctx_new();
  fZMQsocketModeIN = alizmq_socket_init(fZMQin, fZMQcontext, fZMQconfigIN.Data(), -1, 2);
  if (fZMQsocketModeIN < 0) return 1;

  gSystem->ResetSignal(kSigPipe);
  gSystem->ResetSignal(kSigQuit);
  gSystem->ResetSignal(kSigInterrupt);
  gSystem->ResetSignal(kSigTermination);
  //gSystem->AddSignalHandler(new MySignalHandler(kSigPipe));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigQuit));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigInterrupt));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigTermination));

  if (signal(SIGINT, sig_handler) == SIG_ERR)
  printf("\ncan't catch SIGINT\n");

  run(NULL);

  Printf("exiting...");
  if (fFile) fFile->Close();
  delete fFile; fFile=0;

  //destroy ZMQ sockets

  int linger=0;
  zmq_setsockopt(fZMQin, ZMQ_LINGER, &linger, sizeof(linger));
  zmq_close(fZMQin);
  zmq_ctx_term(fZMQcontext);
  return mainReturnCode;
}

//______________________________________________________________________________
int DumpToFile(TObject* object)
{
  Option_t* fileMode="RECREATE";
  if (!fFile) fFile = new TFile(fFileName,fileMode);
  if (fVerbose) Printf("writing object %s to %s",object->GetName(), fFileName.Data());
  int rc = object->Write(object->GetName(),TObject::kOverwrite);
  MySignalHandler::fgTerminationSignaled=true;
  return rc;
}

//______________________________________________________________________________
int UpdatePad(TObject* object)
{
  if (!object) return -1;
  const char* name = object->GetName();

  TObject* drawable = fDrawables.FindObject(name);
  int padIndex = fDrawables.IndexOf(drawable);

  if (fVerbose) Printf("in: %s", name);
  Bool_t selected = kTRUE;
  Bool_t unselected = kFALSE;
  if (fSelectionRegexp) selected = fSelectionRegexp->Match(name);
  if (fUnSelectionRegexp) unselected = fUnSelectionRegexp->Match(name);
  if (!selected || unselected) return 0;

  if (drawable)
  {
    //only redraw the one thing
    if (fVerbose) Printf("  redrawing %s in pad %i", name, padIndex);
    fCanvas->cd(padIndex+1);
    gPad->GetListOfPrimitives()->Remove(drawable);
    gPad->Clear();
    fDrawables.RemoveAt(padIndex);
    delete drawable;
    fDrawables.AddAt(object, padIndex);
    object->Draw(fDrawOptions);
    gPad->Modified(kTRUE);
  }
  else
  {
    if (fVerbose) Printf("  new object %s", name);
    //add the new object to the collection, restructure the canvas
    //and redraw everything
    fDrawables.AddLast(object);

    //after we clear the canvas, the pads are gone, clear the pad cache as well
    fCanvas->Clear();
    fCanvas->DivideSquare(fDrawables.GetLast()+1);

    //redraw all objects at their old places and the new one as last
    for (int i=0; i<fDrawables.GetLast()+1; i++)
    {
      TObject* obj = fDrawables[i];
      fCanvas->cd(i+1);
      if (fScaleLogX) gPad->SetLogx();
      if (fScaleLogY) gPad->SetLogy();
      if (fScaleLogZ) gPad->SetLogz();
      if (fVerbose) Printf("  drawing %s in pad %i", obj->GetName(), i);
      if (obj) obj->Draw();
    }
  }
  gSystem->ProcessEvents();
  fCanvas->Update();
  return 0;
}

//______________________________________________________________________________
int ProcessOptionString(TString arguments)
{
  //process passed options
  stringMap* options = AliOptionParser::TokenizeOptionString(arguments);
  int nOptions = 0;
  for (stringMap::iterator i=options->begin(); i!=options->end(); ++i)
  {
    //Printf("  %s : %s", i->first.data(), i->second.data());
    const TString& option = i->first;
    const TString& value = i->second;
    if (option.EqualTo("PollInterval") || option.EqualTo("sleep"))
    {
      fPollInterval = round(value.Atof()*1e6);
    }
    else if (option.EqualTo("PollTimeout") || option.EqualTo("timeout"))
    {
      fPollTimeout = round(value.Atof()*1e3);
    }
    else if (option.EqualTo("ZMQconfigIN") || option.EqualTo("in") )
    {
      fZMQconfigIN = value;
    }
    else if (option.EqualTo("Verbose"))
    {
      fVerbose=kTRUE;
    }
    else if (option.EqualTo("select"))
    {
      delete fSelectionRegexp;
      fSelectionRegexp=new TPRegexp(value);
    }
    else if (option.EqualTo("unselect"))
    {
      delete fUnSelectionRegexp;
      fUnSelectionRegexp=new TPRegexp(value);
    }
    else if (option.EqualTo("ResetOnRequest"))
    {
      fResetOnRequest = kTRUE;
    }
    else if (option.EqualTo("drawoptions"))
    {
      fDrawOptions = value;
    }
    else if (option.EqualTo("logx"))
    {
      fScaleLogX=kTRUE;
    }
    else if (option.EqualTo("logy"))
    {
      fScaleLogY=kTRUE;
    }
    else if (option.EqualTo("logz"))
    {
      fScaleLogZ=kTRUE;
    }
    else if (option.EqualTo("file"))
    {
      fFileName = value;
    }
    else
    {
      nOptions=-1;
      break;
    }
    nOptions++;
  }
  delete options; //tidy up

  return nOptions;
}

<|endoftext|>


<commit_before>/**
 * Zillians MMO
 * Copyright (C) 2007-2010 Zillians.com, Inc.
 * For more information see http://www.zillians.com
 *
 * Zillians MMO is the library and runtime for massive multiplayer online game
 * development in utility computing model, which runs as a service for every
 * developer to build their virtual world running on our GPU-assisted machines.
 *
 * This is a close source library intended to be used solely within Zillians.com
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
/**
 * @date Sep 1, 2009 sdk - Initial version created.
 */

#include "core/Prerequisite.h"
#include "compiler/tree/ASTNode.h"
#include "compiler/tree/ASTNodeFactory.h"
#include "compiler/tree/visitor/general/GarbageCollectionVisitor.h"
#include <iostream>
#include <string>
#include <limits>

#define BOOST_TEST_MODULE ThorScriptTreeTest_BasicTreeGenerationTest
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

using namespace zillians;
using namespace zillians::compiler::tree;
using namespace zillians::compiler::tree::visitor;

BOOST_AUTO_TEST_SUITE( ThorScriptTreeTest_BasicTreeGenerationTestSuite )

BOOST_AUTO_TEST_CASE( ThorScriptTreeTest_BasicTreeGenerationTestCase1_IsA )
{
	{
		ASTNode *node = new Program(new Package(new SimpleIdentifier(L"")));
		BOOST_CHECK(isa<Program>(node));
		BOOST_CHECK(!isa<Literal>(node));
	}

	{
		ASTNode *node = new BinaryExpr(BinaryExpr::OpCode::ASSIGN, new SimpleIdentifier(L"abc"), new NumericLiteral(123L));
		BOOST_CHECK(isa<Expression>(node));
		BOOST_CHECK(isa<BinaryExpr>(node));
	}

	{
		NestedIdentifier* node = new NestedIdentifier();
		BOOST_CHECK(isa<Identifier>(node));
	}
}

BOOST_AUTO_TEST_CASE( ThorScriptTreeTest_BasicTreeGenerationTestCase2 )
{
	{
		Program* program = new Program(new Package(new SimpleIdentifier(L"")));
		BOOST_CHECK(program->root->id->toString().empty());
	}

	{
		Program* program = new Program();
		BOOST_CHECK(program->root->id->toString().empty()); // the default package name is empty ""
	}
}

BOOST_AUTO_TEST_CASE( ThorScriptTreeTest_BasicTreeGenerationTestCase3 )
{
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>new ASTNode: FunctionType and TypeSpecifier<commit_after>/**
 * Zillians MMO
 * Copyright (C) 2007-2010 Zillians.com, Inc.
 * For more information see http://www.zillians.com
 *
 * Zillians MMO is the library and runtime for massive multiplayer online game
 * development in utility computing model, which runs as a service for every
 * developer to build their virtual world running on our GPU-assisted machines.
 *
 * This is a close source library intended to be used solely within Zillians.com
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
/**
 * @date Sep 1, 2009 sdk - Initial version created.
 */

#include "core/Prerequisite.h"
#include "compiler/tree/ASTNode.h"
#include "compiler/tree/ASTNodeFactory.h"
#include "compiler/tree/visitor/general/GarbageCollectionVisitor.h"
#include <iostream>
#include <string>
#include <limits>

#define BOOST_TEST_MODULE ThorScriptTreeTest_BasicTreeGenerationTest
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

using namespace zillians;
using namespace zillians::compiler::tree;
using namespace zillians::compiler::tree::visitor;

BOOST_AUTO_TEST_SUITE( ThorScriptTreeTest_BasicTreeGenerationTestSuite )

BOOST_AUTO_TEST_CASE( ThorScriptTreeTest_BasicTreeGenerationTestCase1_IsA )
{
	{
		ASTNode *node = new Program(new Package(new SimpleIdentifier(L"")));
		BOOST_CHECK(isa<Program>(node));
		BOOST_CHECK(!isa<Literal>(node));
	}

	{
		ASTNode *node = new BinaryExpr(BinaryExpr::OpCode::ASSIGN, new SimpleIdentifier(L"abc"), new NumericLiteral((uint64)123L));
		BOOST_CHECK(isa<Expression>(node));
		BOOST_CHECK(isa<BinaryExpr>(node));
	}

	{
		NestedIdentifier* node = new NestedIdentifier();
		BOOST_CHECK(isa<Identifier>(node));
	}
}

BOOST_AUTO_TEST_CASE( ThorScriptTreeTest_BasicTreeGenerationTestCase2 )
{
	{
		Program* program = new Program(new Package(new SimpleIdentifier(L"")));
		BOOST_CHECK(program->root->id->toString().empty());
	}

	{
		Program* program = new Program();
		BOOST_CHECK(program->root->id->toString().empty()); // the default package name is empty ""
	}
}

BOOST_AUTO_TEST_CASE( ThorScriptTreeTest_BasicTreeGenerationTestCase3 )
{
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*-----------------------------------------------------------------------------
 This source file is part of Hopsan NG

 Copyright (c) 2011
    Mikael Axin, Robert Braun, Alessandro Dell'Amico, Björn Eriksson,
    Peter Nordin, Karl Pettersson, Petter Krus, Ingo Staack

 This file is provided "as is", with no guarantee or warranty for the
 functionality or reliability of the contents. All contents in this file is
 the original work of the copyright holders at the Division of Fluid and
 Mechatronic Systems (Flumes) at Linköping University. Modifying, using or
 redistributing any part of this file is prohibited without explicit
 permission from the copyright holders.
-----------------------------------------------------------------------------*/

//!
//! @file   HVCWidget.cpp
//! @author Peter Nordin <peter.nordin@liu.se>
//! @date   2012
//!
//! @brief Contains class for Hopsan validation widget
//!
//$Id$

//Qt includes
#include <QCheckBox>
#include <QLabel>
#include <QFileDialog>
#include <QToolButton>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QPushButton>

//Hopsan includes
#include "common.h"
#include "global.h"
#include "GUIObjects/GUISystem.h"
#include "HVCWidget.h"
#include "LogDataHandler.h"
#include "ModelHandler.h"
#include "PlotHandler.h"
#include "Utilities/XMLUtilities.h"
#include "Widgets/ModelWidget.h"
#include "MessageHandler.h"

HVCWidget::HVCWidget(QWidget *parent) :
    QDialog(parent)
{
    mpHvcOpenPathEdit = new QLineEdit();
    QPushButton *pBrowseButton = new QPushButton();
    pBrowseButton->setIcon(QIcon(QString(ICONPATH)+"Hopsan-Open.png"));

    QHBoxLayout *pOpenFileHLayout = new QHBoxLayout();
    pOpenFileHLayout->addWidget(new QLabel("HVC: "));
    pOpenFileHLayout->addWidget(mpHvcOpenPathEdit);
    pOpenFileHLayout->addWidget(pBrowseButton);

    QCheckBox *pFoundModelCheckBox = new QCheckBox();
    QCheckBox *pFoundDataCheckBox = new QCheckBox();
    QHBoxLayout *pOpenStatusHLayout = new QHBoxLayout();
    pOpenStatusHLayout->addWidget(new QLabel("Found model: "));
    pOpenStatusHLayout->addWidget(pFoundModelCheckBox);
    pOpenStatusHLayout->addWidget(new QLabel("Found data: "));
    pOpenStatusHLayout->addWidget(pFoundDataCheckBox);

    mpAllVariablesTree = new FullNameVariableTreeWidget();
    mpSelectedVariablesTree = new FullNameVariableTreeWidget();
    QHBoxLayout *pVariablesHLayout = new QHBoxLayout();

    pVariablesHLayout->addWidget(mpAllVariablesTree);
    pVariablesHLayout->addSpacing(10);
    pVariablesHLayout->addWidget(mpSelectedVariablesTree);

    QHBoxLayout *pButtonLayout = new QHBoxLayout();
    QPushButton *pSaveButton = new QPushButton("Save hvc");
    pSaveButton->setDisabled(true);
    QPushButton *pCloseButton = new QPushButton("Close");
    QPushButton *pCompareButton = new QPushButton("Compare");
    pButtonLayout->addWidget(pCompareButton);
    pButtonLayout->addWidget(pSaveButton);
    pButtonLayout->addWidget(pCloseButton);

    QVBoxLayout *pMainLayout = new QVBoxLayout();
    pMainLayout->addWidget(new QLabel("Not yet finished, but you can use the compare function"));
    pMainLayout->addWidget(new QLabel("You can generate new HVC files from the plotwindow"));
    pMainLayout->addLayout(pOpenFileHLayout);
    pMainLayout->addLayout(pOpenStatusHLayout);
    pMainLayout->addLayout(pVariablesHLayout);
    pMainLayout->addLayout(pButtonLayout);

    this->setLayout(pMainLayout);

    connect(pCloseButton, SIGNAL(clicked()), this, SLOT(close()));
    connect(pBrowseButton, SIGNAL(clicked()), this, SLOT(openHvcFile()));
    connect(pCompareButton, SIGNAL(clicked()), this, SLOT(runHvcTest()));

    this->resize(800, 600);
    this->setWindowTitle("Hopsan Model Validation");

}

void HVCWidget::openHvcFile()
{
    QFile hvcFile;
    hvcFile.setFileName(QFileDialog::getOpenFileName(this, "Select a HVC file"));
    if (hvcFile.exists())
    {
        // Clear
        clearContents();

        QFileInfo hvcFileInfo = QFileInfo(hvcFile);
        QDomDocument xmlDocument;
        QDomElement rootElement = loadXMLDomDocument(hvcFile, xmlDocument, "hopsanvalidationconfiguration");
        if (rootElement.isNull())
        {
            //! @todo some error message
            return;
        }

        QFile hmfFile, dataFile;
        if (rootElement.attribute("hvcversion") == "0.1")
        {
            // Load old format
            QDomElement xmlValidation = rootElement.firstChildElement("validation");
            QString modelFilePath = xmlValidation.firstChildElement("modelfile").text();
            if (modelFilePath.isEmpty())
            {
                // Use same name as hvc file instead
                modelFilePath = hvcFileInfo.absolutePath()+"/"+hvcFileInfo.baseName()+".hmf";
            }
            else
            {
                // Make sure absoulte, the loaded modelpath should be relative to the hvc file
                modelFilePath = hvcFileInfo.absolutePath()+"/"+modelFilePath;
            }
            hmfFile.setFileName(modelFilePath);

            if (hmfFile.exists())
            {
                mModelFilePath = modelFilePath;
                QDomElement xmlComponent = xmlValidation.firstChildElement("component");
                while (!xmlComponent.isNull())
                {
                    QDomElement xmlPort = xmlComponent.firstChildElement("port");
                    while (!xmlPort.isNull())
                    {
                        QString dataFilePath = xmlComponent.firstChildElement("csvfile").text();
                        if (dataFilePath.isEmpty())
                        {
                            // Use same name as hvc file instead
                            dataFilePath = hvcFileInfo.absolutePath()+"/"+hvcFileInfo.baseName()+".csv";
                        }
                        dataFile.setFileName(dataFilePath);

                        QDomElement xmlVariable = xmlPort.firstChildElement("variable");
                        while (!xmlVariable.isNull())
                        {
                            // check if we should override data file
                            if (!xmlComponent.firstChildElement("csvfile").isNull())
                            {
                                QString dataFilePath = xmlComponent.firstChildElement("csvfile").text();
                                if (dataFilePath.isEmpty())
                                {
                                    // Use same name as hvc file instead
                                    dataFilePath = hvcFileInfo.absolutePath()+"/"+hvcFileInfo.baseName()+".csv";
                                }
                                dataFile.setFileName(dataFilePath);
                            }

                            HvcConfig conf;
                            conf.mDataColumn = parseDomIntegerNode(xmlVariable.firstChildElement("column"), 0);
                            conf.mTolerance = parseDomValueNode(xmlVariable.firstChildElement("tolerance"), conf.mTolerance);
                            conf.mFullVarName = xmlComponent.attribute("name")+"#"+xmlPort.attribute("name")+"#"+xmlVariable.attribute("name");
                            conf.mDataFile = dataFile.fileName();
                            mDataConfigs.append(conf);

                            // Populate the tree
                            mpAllVariablesTree->addFullNameVariable(conf.mFullVarName);
                            mpSelectedVariablesTree->addFullNameVariable(conf.mFullVarName);

                            // Next variable to check
                            xmlVariable = xmlVariable.nextSiblingElement("variable");
                        }
                        xmlPort = xmlPort.nextSiblingElement("port");
                    }
                    xmlComponent = xmlComponent.nextSiblingElement("component");
                }
            }
            else
            {
                //! @todo some error
            }
        }
        else if (rootElement.attribute("hvcversion") == "0.2")
        {
            // Get model to load
            QDomElement xmlValidation = rootElement.firstChildElement("validation");
            QString modelFilePath = xmlValidation.firstChildElement("modelfile").text();
            if (modelFilePath.isEmpty())
            {
                // Use same name as hvc file instead
                modelFilePath = hvcFileInfo.absolutePath()+"/"+hvcFileInfo.baseName()+".hmf";
            }
            else
            {
                // Make sure absoulte, the loaded modelpath should be relative to the hvc file
                modelFilePath = hvcFileInfo.absolutePath()+"/"+modelFilePath;
            }
            hmfFile.setFileName(modelFilePath);

            if (hmfFile.exists())
            {
                mModelFilePath = modelFilePath;

                QString dataFilePath = xmlValidation.firstChildElement("hvdfile").text();
                if (dataFilePath.isEmpty())
                {
                    // Use same name as hvc file instead
                    dataFilePath = hvcFileInfo.absolutePath()+"/"+hvcFileInfo.baseName()+".hvd";
                }
                else
                {
                    // Make sure absoulte, the loaded datafilepath should be relative to the hvc file
                    dataFilePath = hvcFileInfo.absolutePath()+"/"+dataFilePath;
                }
                dataFile.setFileName(dataFilePath);

                QDomElement xmlVariable = xmlValidation.firstChildElement("variable");
                while (!xmlVariable.isNull())
                {
                    HvcConfig conf;
                    conf.mDataColumn = parseDomIntegerNode(xmlVariable.firstChildElement("column"), 0);
                    conf.mTimeColumn = parseDomIntegerNode(xmlVariable.firstChildElement("timecolumn"), 0);
                    conf.mTolerance = parseDomValueNode(xmlVariable.firstChildElement("tolerance"), conf.mTolerance);
                    conf.mFullVarName = xmlVariable.attribute("name");
                    conf.mDataFile = dataFile.fileName();
                    mDataConfigs.append(conf);

                    // Populate the tree
                    mpAllVariablesTree->addFullNameVariable(conf.mFullVarName);
                    mpSelectedVariablesTree->addFullNameVariable(conf.mFullVarName);

                    // Next variable to check
                    xmlVariable = xmlVariable.nextSiblingElement("variable");
                }
            }
            else
            {
                //! @todo some error
            }

        }
        else
        {
            // Unsupported format
        }

        // Show file in line edit
        mpHvcOpenPathEdit->setText(hvcFile.fileName());

        // Find model and any data files, update status

        // Populate tree

    }
}

void HVCWidget::clearContents()
{
    mpHvcOpenPathEdit->clear();
    mpAllVariablesTree->clear();
    mpSelectedVariablesTree->clear();
    mModelFilePath.clear();
    mDataConfigs.clear();
}

void HVCWidget::runHvcTest()
{
    // First load the model
    gpModelHandler->loadModel(mModelFilePath, true);
    // Switch to that tab

    // Simulate the system
    if (gpModelHandler->getCurrentModel())
    {
        gpModelHandler->getCurrentModel()->simulate_blocking();
    }

    // Run each test
    gpPlotHandler->closeAllOpenWindows(); //Close all plot windows to avoid confusion if we run several tests after each other
    for (int t=0; t<mDataConfigs.size(); ++t)
    {
        LogDataHandler *pImportLogDataHandler = gpModelHandler->getCurrentTopLevelSystem()->getLogDataHandler();
        LogDataHandler *pVariableLogDataHandler = pImportLogDataHandler;
        QString variableName = mDataConfigs[t].mFullVarName;

        // Handle subsystem variables
        if (variableName.contains('$'))
        {
            QStringList fields = variableName.split('$');
            fields.erase(fields.begin()); // Remove the first "top-level system" name
            ContainerObject *pContainer=gpModelHandler->getCurrentTopLevelSystem();
            while (!fields.front().contains('#'))
            {
                ModelObject *pObj = pContainer->getModelObject(fields.front());
                if (pObj && (pObj->type() == SystemContainerType))
                {
                    pContainer = qobject_cast<ContainerObject*>(pObj);
                }
                else
                {
                    gpMessageHandler->addErrorMessage(QString("Could not find system: %1").arg(fields.front()));
                    return;
                }
                fields.erase(fields.begin());
            }
            pVariableLogDataHandler = pContainer->getLogDataHandler();
            variableName = fields.front();
        }

        QVector<int> columns, timecolumns;
        QStringList names;
        columns.append(mDataConfigs[t].mDataColumn);
        timecolumns.append(mDataConfigs[t].mTimeColumn);
        names.append(mDataConfigs[t].mFullVarName+"_valid");

        pImportLogDataHandler->importTimeVariablesFromCSVColumns(mDataConfigs[t].mDataFile, columns, names, timecolumns);

        QString windowName = QString("Validation Plot %1").arg(t);
        gpPlotHandler->createNewOrReplacePlotwindow(windowName);
        gpPlotHandler->plotDataToWindow(windowName, pVariableLogDataHandler->getVectorVariable(variableName,-1), 0);
        gpPlotHandler->plotDataToWindow(windowName, pImportLogDataHandler->getVectorVariable(mDataConfigs[t].mFullVarName+"_valid",-1), 0);
    }
}

void FullNameVariableTreeWidget::addFullNameVariable(const QString &rFullName, const QString &rRemaningName, QTreeWidgetItem *pParentItem)
{
    if (!rFullName.isEmpty())
    {
        bool isLeaf=false;
        QStringList systems = rRemaningName.split("$");
        QString name;

        // If we have a system part
        if (systems.size() > 1)
        {
            name = systems.first();
        }
        // Else we have a comp::port::var
        else
        {
            QStringList compportvar = rRemaningName.split("#");
            if (compportvar.size()==1)
            {
                isLeaf = true;
            }
            name = compportvar.first();
        }

        QTreeWidgetItem* pLevelItem=0;
        // Add a new level in the tree
        if (pParentItem)
        {
            QTreeWidgetItem* pFound=0;
            for (int c=0; c<pParentItem->childCount(); ++c)
            {
                if (pParentItem->child(c)->text(0) == name)
                {
                    // We assume there will never be duplicates due to uniqe name requirements
                    pFound = pParentItem->child(c);
                    break;
                }
            }

            if (pFound)
            {
                pLevelItem = pFound;
            }
            else
            {
                // Add new item
                pLevelItem = new QTreeWidgetItem(QStringList(name));
                pParentItem->addChild(pLevelItem);
            }
        }
        else
        {
            QList<QTreeWidgetItem*> found = this->findItems(name, 0);
            if (found.isEmpty())
            {
                // Add new top level item
                pLevelItem = new QTreeWidgetItem(QStringList(name));
                addTopLevelItem(pLevelItem);
            }
            else
            {
                // We assume there will never be duplicates due to uniqe name requirements
                pLevelItem = found.first();
            }

        }

        if (isLeaf)
        {
            pLevelItem->setData(0,Qt::UserRole,rFullName);
        }
        else
        {
            // Recurse
            QString shorterRemaningName = rRemaningName;
            shorterRemaningName.remove(0, name.size()+1);
            addFullNameVariable(rFullName, shorterRemaningName, pLevelItem);
        }
    }
}

FullNameVariableTreeWidget::FullNameVariableTreeWidget(QWidget *pParent) : QTreeWidget(pParent)
{
    //Nothing
}

void FullNameVariableTreeWidget::addFullNameVariable(const QString &rFullName)
{
    addFullNameVariable(rFullName, rFullName, 0);
}

//void FullNameVariableTreeWidget::mousePressEvent(QMouseEvent *event)
//{
//    QTreeWidget::mousePressEvent(event);

//    //! @todo dragstartposition
//    QTreeWidgetItem *pItem = this->itemAt(event->pos());

//    if (pItem && (pItem->childCount() == 0))
//    {
//        QDrag *pDrag = new QDrag(this);
//        QMimeData *pMime = new QMimeData;

//        pMime->setText(pItem->data(0, Qt::UserRole).toString());
//        pDrag->setMimeData(pMime);

//        Qt::DropAction dropAction = pDrag->exec(Qt::CopyAction | Qt::MoveAction);
//    }
//}

//void FullNameVariableTreeWidget::dropEvent(QDropEvent *event)
//{
//    if (!event->mimeData()->text().isEmpty())
//    {
//        addFullNameVariable(event->mimeData()->text());
//        event->acceptProposedAction();
//    }
//}

//void FullNameVariableTreeWidget::dragEnterEvent(QDragEnterEvent *event)
//{
//    if (!event->mimeData()->text().isEmpty())
//    {
//        event->acceptProposedAction();
//    }
//}
<commit_msg>Fixed uninitialized variable<commit_after>/*-----------------------------------------------------------------------------
 This source file is part of Hopsan NG

 Copyright (c) 2011
    Mikael Axin, Robert Braun, Alessandro Dell'Amico, Björn Eriksson,
    Peter Nordin, Karl Pettersson, Petter Krus, Ingo Staack

 This file is provided "as is", with no guarantee or warranty for the
 functionality or reliability of the contents. All contents in this file is
 the original work of the copyright holders at the Division of Fluid and
 Mechatronic Systems (Flumes) at Linköping University. Modifying, using or
 redistributing any part of this file is prohibited without explicit
 permission from the copyright holders.
-----------------------------------------------------------------------------*/

//!
//! @file   HVCWidget.cpp
//! @author Peter Nordin <peter.nordin@liu.se>
//! @date   2012
//!
//! @brief Contains class for Hopsan validation widget
//!
//$Id$

//Qt includes
#include <QCheckBox>
#include <QLabel>
#include <QFileDialog>
#include <QToolButton>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QPushButton>

//Hopsan includes
#include "common.h"
#include "global.h"
#include "GUIObjects/GUISystem.h"
#include "HVCWidget.h"
#include "LogDataHandler.h"
#include "ModelHandler.h"
#include "PlotHandler.h"
#include "Utilities/XMLUtilities.h"
#include "Widgets/ModelWidget.h"
#include "MessageHandler.h"

HVCWidget::HVCWidget(QWidget *parent) :
    QDialog(parent)
{
    mpHvcOpenPathEdit = new QLineEdit();
    QPushButton *pBrowseButton = new QPushButton();
    pBrowseButton->setIcon(QIcon(QString(ICONPATH)+"Hopsan-Open.png"));

    QHBoxLayout *pOpenFileHLayout = new QHBoxLayout();
    pOpenFileHLayout->addWidget(new QLabel("HVC: "));
    pOpenFileHLayout->addWidget(mpHvcOpenPathEdit);
    pOpenFileHLayout->addWidget(pBrowseButton);

    QCheckBox *pFoundModelCheckBox = new QCheckBox();
    QCheckBox *pFoundDataCheckBox = new QCheckBox();
    QHBoxLayout *pOpenStatusHLayout = new QHBoxLayout();
    pOpenStatusHLayout->addWidget(new QLabel("Found model: "));
    pOpenStatusHLayout->addWidget(pFoundModelCheckBox);
    pOpenStatusHLayout->addWidget(new QLabel("Found data: "));
    pOpenStatusHLayout->addWidget(pFoundDataCheckBox);

    mpAllVariablesTree = new FullNameVariableTreeWidget();
    mpSelectedVariablesTree = new FullNameVariableTreeWidget();
    QHBoxLayout *pVariablesHLayout = new QHBoxLayout();

    pVariablesHLayout->addWidget(mpAllVariablesTree);
    pVariablesHLayout->addSpacing(10);
    pVariablesHLayout->addWidget(mpSelectedVariablesTree);

    QHBoxLayout *pButtonLayout = new QHBoxLayout();
    QPushButton *pSaveButton = new QPushButton("Save hvc");
    pSaveButton->setDisabled(true);
    QPushButton *pCloseButton = new QPushButton("Close");
    QPushButton *pCompareButton = new QPushButton("Compare");
    pButtonLayout->addWidget(pCompareButton);
    pButtonLayout->addWidget(pSaveButton);
    pButtonLayout->addWidget(pCloseButton);

    QVBoxLayout *pMainLayout = new QVBoxLayout();
    pMainLayout->addWidget(new QLabel("Not yet finished, but you can use the compare function"));
    pMainLayout->addWidget(new QLabel("You can generate new HVC files from the plotwindow"));
    pMainLayout->addLayout(pOpenFileHLayout);
    pMainLayout->addLayout(pOpenStatusHLayout);
    pMainLayout->addLayout(pVariablesHLayout);
    pMainLayout->addLayout(pButtonLayout);

    this->setLayout(pMainLayout);

    connect(pCloseButton, SIGNAL(clicked()), this, SLOT(close()));
    connect(pBrowseButton, SIGNAL(clicked()), this, SLOT(openHvcFile()));
    connect(pCompareButton, SIGNAL(clicked()), this, SLOT(runHvcTest()));

    this->resize(800, 600);
    this->setWindowTitle("Hopsan Model Validation");

}

void HVCWidget::openHvcFile()
{
    QFile hvcFile;
    hvcFile.setFileName(QFileDialog::getOpenFileName(this, "Select a HVC file"));
    if (hvcFile.exists())
    {
        // Clear
        clearContents();

        QFileInfo hvcFileInfo = QFileInfo(hvcFile);
        QDomDocument xmlDocument;
        QDomElement rootElement = loadXMLDomDocument(hvcFile, xmlDocument, "hopsanvalidationconfiguration");
        if (rootElement.isNull())
        {
            //! @todo some error message
            return;
        }

        QFile hmfFile, dataFile;
        if (rootElement.attribute("hvcversion") == "0.1")
        {
            // Load old format
            QDomElement xmlValidation = rootElement.firstChildElement("validation");
            QString modelFilePath = xmlValidation.firstChildElement("modelfile").text();
            if (modelFilePath.isEmpty())
            {
                // Use same name as hvc file instead
                modelFilePath = hvcFileInfo.absolutePath()+"/"+hvcFileInfo.baseName()+".hmf";
            }
            else
            {
                // Make sure absoulte, the loaded modelpath should be relative to the hvc file
                modelFilePath = hvcFileInfo.absolutePath()+"/"+modelFilePath;
            }
            hmfFile.setFileName(modelFilePath);

            if (hmfFile.exists())
            {
                mModelFilePath = modelFilePath;
                QDomElement xmlComponent = xmlValidation.firstChildElement("component");
                while (!xmlComponent.isNull())
                {
                    QDomElement xmlPort = xmlComponent.firstChildElement("port");
                    while (!xmlPort.isNull())
                    {
                        QString dataFilePath = xmlComponent.firstChildElement("csvfile").text();
                        if (dataFilePath.isEmpty())
                        {
                            // Use same name as hvc file instead
                            dataFilePath = hvcFileInfo.absolutePath()+"/"+hvcFileInfo.baseName()+".csv";
                        }
                        dataFile.setFileName(dataFilePath);

                        QDomElement xmlVariable = xmlPort.firstChildElement("variable");
                        while (!xmlVariable.isNull())
                        {
                            // check if we should override data file
                            if (!xmlComponent.firstChildElement("csvfile").isNull())
                            {
                                QString dataFilePath = xmlComponent.firstChildElement("csvfile").text();
                                if (dataFilePath.isEmpty())
                                {
                                    // Use same name as hvc file instead
                                    dataFilePath = hvcFileInfo.absolutePath()+"/"+hvcFileInfo.baseName()+".csv";
                                }
                                dataFile.setFileName(dataFilePath);
                            }

                            HvcConfig conf;
                            conf.mDataColumn = parseDomIntegerNode(xmlVariable.firstChildElement("column"), 0);
                            conf.mTimeColumn = 0;
                            conf.mTolerance = parseDomValueNode(xmlVariable.firstChildElement("tolerance"), conf.mTolerance);
                            conf.mFullVarName = xmlComponent.attribute("name")+"#"+xmlPort.attribute("name")+"#"+xmlVariable.attribute("name");
                            conf.mDataFile = dataFile.fileName();
                            mDataConfigs.append(conf);

                            // Populate the tree
                            mpAllVariablesTree->addFullNameVariable(conf.mFullVarName);
                            mpSelectedVariablesTree->addFullNameVariable(conf.mFullVarName);

                            // Next variable to check
                            xmlVariable = xmlVariable.nextSiblingElement("variable");
                        }
                        xmlPort = xmlPort.nextSiblingElement("port");
                    }
                    xmlComponent = xmlComponent.nextSiblingElement("component");
                }
            }
            else
            {
                //! @todo some error
            }
        }
        else if (rootElement.attribute("hvcversion") == "0.2")
        {
            // Get model to load
            QDomElement xmlValidation = rootElement.firstChildElement("validation");
            QString modelFilePath = xmlValidation.firstChildElement("modelfile").text();
            if (modelFilePath.isEmpty())
            {
                // Use same name as hvc file instead
                modelFilePath = hvcFileInfo.absolutePath()+"/"+hvcFileInfo.baseName()+".hmf";
            }
            else
            {
                // Make sure absoulte, the loaded modelpath should be relative to the hvc file
                modelFilePath = hvcFileInfo.absolutePath()+"/"+modelFilePath;
            }
            hmfFile.setFileName(modelFilePath);

            if (hmfFile.exists())
            {
                mModelFilePath = modelFilePath;

                QString dataFilePath = xmlValidation.firstChildElement("hvdfile").text();
                if (dataFilePath.isEmpty())
                {
                    // Use same name as hvc file instead
                    dataFilePath = hvcFileInfo.absolutePath()+"/"+hvcFileInfo.baseName()+".hvd";
                }
                else
                {
                    // Make sure absoulte, the loaded datafilepath should be relative to the hvc file
                    dataFilePath = hvcFileInfo.absolutePath()+"/"+dataFilePath;
                }
                dataFile.setFileName(dataFilePath);

                QDomElement xmlVariable = xmlValidation.firstChildElement("variable");
                while (!xmlVariable.isNull())
                {
                    HvcConfig conf;
                    conf.mDataColumn = parseDomIntegerNode(xmlVariable.firstChildElement("column"), 0);
                    conf.mTimeColumn = parseDomIntegerNode(xmlVariable.firstChildElement("timecolumn"), 0);
                    conf.mTolerance = parseDomValueNode(xmlVariable.firstChildElement("tolerance"), conf.mTolerance);
                    conf.mFullVarName = xmlVariable.attribute("name");
                    conf.mDataFile = dataFile.fileName();
                    mDataConfigs.append(conf);

                    // Populate the tree
                    mpAllVariablesTree->addFullNameVariable(conf.mFullVarName);
                    mpSelectedVariablesTree->addFullNameVariable(conf.mFullVarName);

                    // Next variable to check
                    xmlVariable = xmlVariable.nextSiblingElement("variable");
                }
            }
            else
            {
                //! @todo some error
            }

        }
        else
        {
            // Unsupported format
        }

        // Show file in line edit
        mpHvcOpenPathEdit->setText(hvcFile.fileName());

        // Find model and any data files, update status

        // Populate tree

    }
}

void HVCWidget::clearContents()
{
    mpHvcOpenPathEdit->clear();
    mpAllVariablesTree->clear();
    mpSelectedVariablesTree->clear();
    mModelFilePath.clear();
    mDataConfigs.clear();
}

void HVCWidget::runHvcTest()
{
    // First load the model
    gpModelHandler->loadModel(mModelFilePath, true);
    // Switch to that tab

    // Simulate the system
    if (gpModelHandler->getCurrentModel())
    {
        gpModelHandler->getCurrentModel()->simulate_blocking();
    }

    // Run each test
    gpPlotHandler->closeAllOpenWindows(); //Close all plot windows to avoid confusion if we run several tests after each other
    for (int t=0; t<mDataConfigs.size(); ++t)
    {
        LogDataHandler *pImportLogDataHandler = gpModelHandler->getCurrentTopLevelSystem()->getLogDataHandler();
        LogDataHandler *pVariableLogDataHandler = pImportLogDataHandler;
        QString variableName = mDataConfigs[t].mFullVarName;

        // Handle subsystem variables
        if (variableName.contains('$'))
        {
            QStringList fields = variableName.split('$');
            fields.erase(fields.begin()); // Remove the first "top-level system" name
            ContainerObject *pContainer=gpModelHandler->getCurrentTopLevelSystem();
            while (!fields.front().contains('#'))
            {
                ModelObject *pObj = pContainer->getModelObject(fields.front());
                if (pObj && (pObj->type() == SystemContainerType))
                {
                    pContainer = qobject_cast<ContainerObject*>(pObj);
                }
                else
                {
                    gpMessageHandler->addErrorMessage(QString("Could not find system: %1").arg(fields.front()));
                    return;
                }
                fields.erase(fields.begin());
            }
            pVariableLogDataHandler = pContainer->getLogDataHandler();
            variableName = fields.front();
        }

        QVector<int> columns, timecolumns;
        QStringList names;
        columns.append(mDataConfigs[t].mDataColumn);
        timecolumns.append(mDataConfigs[t].mTimeColumn);
        names.append(mDataConfigs[t].mFullVarName+"_valid");

        pImportLogDataHandler->importTimeVariablesFromCSVColumns(mDataConfigs[t].mDataFile, columns, names, timecolumns);

        QString windowName = QString("Validation Plot %1").arg(t);
        gpPlotHandler->createNewOrReplacePlotwindow(windowName);
        gpPlotHandler->plotDataToWindow(windowName, pVariableLogDataHandler->getVectorVariable(variableName,-1), 0);
        gpPlotHandler->plotDataToWindow(windowName, pImportLogDataHandler->getVectorVariable(mDataConfigs[t].mFullVarName+"_valid",-1), 0);
    }
}

void FullNameVariableTreeWidget::addFullNameVariable(const QString &rFullName, const QString &rRemaningName, QTreeWidgetItem *pParentItem)
{
    if (!rFullName.isEmpty())
    {
        bool isLeaf=false;
        QStringList systems = rRemaningName.split("$");
        QString name;

        // If we have a system part
        if (systems.size() > 1)
        {
            name = systems.first();
        }
        // Else we have a comp::port::var
        else
        {
            QStringList compportvar = rRemaningName.split("#");
            if (compportvar.size()==1)
            {
                isLeaf = true;
            }
            name = compportvar.first();
        }

        QTreeWidgetItem* pLevelItem=0;
        // Add a new level in the tree
        if (pParentItem)
        {
            QTreeWidgetItem* pFound=0;
            for (int c=0; c<pParentItem->childCount(); ++c)
            {
                if (pParentItem->child(c)->text(0) == name)
                {
                    // We assume there will never be duplicates due to uniqe name requirements
                    pFound = pParentItem->child(c);
                    break;
                }
            }

            if (pFound)
            {
                pLevelItem = pFound;
            }
            else
            {
                // Add new item
                pLevelItem = new QTreeWidgetItem(QStringList(name));
                pParentItem->addChild(pLevelItem);
            }
        }
        else
        {
            QList<QTreeWidgetItem*> found = this->findItems(name, 0);
            if (found.isEmpty())
            {
                // Add new top level item
                pLevelItem = new QTreeWidgetItem(QStringList(name));
                addTopLevelItem(pLevelItem);
            }
            else
            {
                // We assume there will never be duplicates due to uniqe name requirements
                pLevelItem = found.first();
            }

        }

        if (isLeaf)
        {
            pLevelItem->setData(0,Qt::UserRole,rFullName);
        }
        else
        {
            // Recurse
            QString shorterRemaningName = rRemaningName;
            shorterRemaningName.remove(0, name.size()+1);
            addFullNameVariable(rFullName, shorterRemaningName, pLevelItem);
        }
    }
}

FullNameVariableTreeWidget::FullNameVariableTreeWidget(QWidget *pParent) : QTreeWidget(pParent)
{
    //Nothing
}

void FullNameVariableTreeWidget::addFullNameVariable(const QString &rFullName)
{
    addFullNameVariable(rFullName, rFullName, 0);
}

//void FullNameVariableTreeWidget::mousePressEvent(QMouseEvent *event)
//{
//    QTreeWidget::mousePressEvent(event);

//    //! @todo dragstartposition
//    QTreeWidgetItem *pItem = this->itemAt(event->pos());

//    if (pItem && (pItem->childCount() == 0))
//    {
//        QDrag *pDrag = new QDrag(this);
//        QMimeData *pMime = new QMimeData;

//        pMime->setText(pItem->data(0, Qt::UserRole).toString());
//        pDrag->setMimeData(pMime);

//        Qt::DropAction dropAction = pDrag->exec(Qt::CopyAction | Qt::MoveAction);
//    }
//}

//void FullNameVariableTreeWidget::dropEvent(QDropEvent *event)
//{
//    if (!event->mimeData()->text().isEmpty())
//    {
//        addFullNameVariable(event->mimeData()->text());
//        event->acceptProposedAction();
//    }
//}

//void FullNameVariableTreeWidget::dragEnterEvent(QDragEnterEvent *event)
//{
//    if (!event->mimeData()->text().isEmpty())
//    {
//        event->acceptProposedAction();
//    }
//}
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#ifndef MITKDIFFUSIONIMAGETODIFFUSIONIMAGEFILTER_CPP
#define MITKDIFFUSIONIMAGETODIFFUSIONIMAGEFILTER_CPP

#include "mitkDWIHeadMotionCorrectionFilter.h"

#include "itkSplitDWImageFilter.h"
#include "itkB0ImageExtractionToSeparateImageFilter.h"

#include "mitkImageTimeSelector.h"

#include "mitkPyramidImageRegistrationMethod.h"
#include "mitkImageToDiffusionImageSource.h"

#include "mitkDiffusionImageCorrectionFilter.h"

#include <vector>

#include "mitkIOUtil.h"
#include <itkImage.h>

template< typename DiffusionPixelType>
mitk::DWIHeadMotionCorrectionFilter<DiffusionPixelType>
  ::DWIHeadMotionCorrectionFilter():
m_CurrentStep(0),
  m_Steps(100),
  m_IsInValidState(true),
  m_AbortRegistration(false)
{

}

template< typename DiffusionPixelType>
void mitk::DWIHeadMotionCorrectionFilter<DiffusionPixelType>
  ::GenerateData()
{
  typedef itk::SplitDWImageFilter< DiffusionPixelType, DiffusionPixelType> SplitFilterType;

  DiffusionImageType* input = const_cast<DiffusionImageType*>(this->GetInput(0));

  unsigned int numberOfSteps = input->GetVectorImage()->GetNumberOfComponentsPerPixel () ;
  m_Steps = numberOfSteps;
  //
  //  (1) Extract the b-zero images to a 3d+t image, register them by NCorr metric and
  //     rigid registration : they will then be used are reference image for registering
  //     the gradient images
  //
  typedef itk::B0ImageExtractionToSeparateImageFilter< DiffusionPixelType, DiffusionPixelType> B0ExtractorType;
  typename B0ExtractorType::Pointer b0_extractor = B0ExtractorType::New();
  b0_extractor->SetInput( input->GetVectorImage() );
  b0_extractor->SetDirections( input->GetDirections() );
  b0_extractor->Update();

  mitk::Image::Pointer b0Image = mitk::Image::New();
  b0Image->InitializeByItk( b0_extractor->GetOutput() );
  b0Image->SetImportChannel( b0_extractor->GetOutput()->GetBufferPointer(),
    mitk::Image::CopyMemory );

  // (2.1) Use the extractor to access the extracted b0 volumes
  mitk::ImageTimeSelector::Pointer t_selector =
    mitk::ImageTimeSelector::New();

  t_selector->SetInput( b0Image );
  t_selector->SetTimeNr(0);
  t_selector->Update();

  // first unweighted image as reference space for the registration
  mitk::Image::Pointer b0referenceImage = t_selector->GetOutput();

  mitk::PyramidImageRegistrationMethod::Pointer registrationMethod = mitk::PyramidImageRegistrationMethod::New();
  registrationMethod->SetFixedImage( b0referenceImage );
  registrationMethod->SetTransformToRigid();

  // the unweighted images are of same modality
  registrationMethod->SetCrossModalityOff();

  // use the advanced (windowed sinc) interpolation
  registrationMethod->SetUseAdvancedInterpolation(true);

  // Initialize the temporary output image
  mitk::Image::Pointer registeredB0Image = b0Image->Clone();
  const unsigned int numberOfb0Images = b0Image->GetTimeSteps();

  if( numberOfb0Images > 1)
  {
    mitk::ImageTimeSelector::Pointer t_selector2 =
      mitk::ImageTimeSelector::New();

    t_selector2->SetInput( b0Image );

    for( unsigned int i=1; i<numberOfb0Images; i++)
    {

      m_CurrentStep = i + 1;
      if( m_AbortRegistration == true) {
        m_IsInValidState = false;
        mitkThrow() << "Stopped by user.";
      };

      t_selector2->SetTimeNr(i);
      t_selector2->Update();

      registrationMethod->SetMovingImage( t_selector2->GetOutput() );

      try
      {
        MITK_INFO << " === (" << i <<"/"<< numberOfb0Images-1 << ") :: Starting registration";
        registrationMethod->Update();
      }
      catch( const itk::ExceptionObject& e)
      {
        m_IsInValidState = false;
        mitkThrow() << "Failed to register the b0 images, the PyramidRegistration threw an exception: \n" << e.what();
      }

      // import volume to the inter-results
      registeredB0Image->SetImportVolume( registrationMethod->GetResampledMovingImage()->GetData(),
        i, 0, mitk::Image::ReferenceMemory );

    }

    // use the accumulateImageFilter as provided by the ItkAccumulateFilter method in the header file
    AccessFixedDimensionByItk_1(registeredB0Image, ItkAccumulateFilter, (4), b0referenceImage );

  }

  //
  // (2) Split the diffusion image into a 3d+t regular image, extract only the weighted images
  //
  typename SplitFilterType::Pointer split_filter = SplitFilterType::New();
  split_filter->SetInput (input->GetVectorImage() );
  split_filter->SetExtractAllAboveThreshold(20, input->GetB_ValueMap() );

  try
  {
    split_filter->Update();
  }
  catch( const itk::ExceptionObject &e)
  {
    m_IsInValidState = false;
    mitkThrow() << " Caught exception from SplitImageFilter : " << e.what();
  }

  mitk::Image::Pointer splittedImage = mitk::Image::New();
  splittedImage->InitializeByItk( split_filter->GetOutput() );
  splittedImage->SetImportChannel( split_filter->GetOutput()->GetBufferPointer(),
    mitk::Image::CopyMemory );

  //
  // (3) Use again the time-selector to access the components separately in order
  //     to perform the registration of  Image -> unweighted reference
  //

  mitk::PyramidImageRegistrationMethod::Pointer weightedRegistrationMethod
    = mitk::PyramidImageRegistrationMethod::New();

  weightedRegistrationMethod->SetTransformToAffine();
  weightedRegistrationMethod->SetCrossModalityOn();

  //
  //   - (3.1) Set the reference image
  //      - a single b0 image
  //      - average over the registered b0 images if multiple present
  //
  weightedRegistrationMethod->SetFixedImage( b0referenceImage );
  // use the advanced (windowed sinc) interpolation
  weightedRegistrationMethod->SetUseAdvancedInterpolation(true);

  //
  //   - (3.2) Register all timesteps in the splitted image onto the first reference
  //
  unsigned int maxImageIdx = splittedImage->GetTimeSteps();
  mitk::TimeGeometry* tsg = splittedImage->GetTimeGeometry();
  mitk::ProportionalTimeGeometry* ptg = dynamic_cast<ProportionalTimeGeometry*>(tsg);
  ptg->Expand(maxImageIdx+1);

  mitk::Image::Pointer registeredWeighted = mitk::Image::New();
  registeredWeighted->Initialize( splittedImage->GetPixelType(0), *tsg );

  // insert the first unweighted reference as the first volume
  registeredWeighted->SetImportVolume( b0referenceImage->GetData(),
    0,0, mitk::Image::CopyMemory );

  // mitk::Image::Pointer registeredWeighted = splittedImage->Clone();
  // this time start at 0, we have only gradient images in the 3d+t file
  // the reference image comes form an other image
  mitk::ImageTimeSelector::Pointer t_selector_w =
    mitk::ImageTimeSelector::New();

  t_selector_w->SetInput( splittedImage );

  // store the rotation parts of the transformations in a vector
  typedef mitk::PyramidImageRegistrationMethod::TransformMatrixType MatrixType;
  std::vector< MatrixType > estimated_transforms;

  for( unsigned int i=0; i<maxImageIdx; i++)
  {
    m_CurrentStep = numberOfb0Images + i + 1;
    if( m_AbortRegistration == true) {
      m_IsInValidState = false;
      mitkThrow() << "Stopped by user.";
    };

    t_selector_w->SetTimeNr(i);
    t_selector_w->Update();

    weightedRegistrationMethod->SetMovingImage( t_selector_w->GetOutput() );

    try
    {
      MITK_INFO << " === (" << i+1 <<"/"<< maxImageIdx << ") :: Starting registration";
      weightedRegistrationMethod->Update();
    }
    catch( const itk::ExceptionObject& e)
    {
      m_IsInValidState = false;
      mitkThrow() << "Failed to register the b0 images, the PyramidRegistration threw an exception: \n" << e.what();
    }

    // allow expansion
    registeredWeighted->SetImportVolume( weightedRegistrationMethod->GetResampledMovingImage()->GetData(),
      i+1, 0, mitk::Image::CopyMemory);

    estimated_transforms.push_back( weightedRegistrationMethod->GetLastRotationMatrix() );
  }

  //
  // (4) Cast the resulting image back to an diffusion weighted image
  //
  typename DiffusionImageType::GradientDirectionContainerType *gradients = input->GetDirections();
  typename DiffusionImageType::GradientDirectionContainerType::Pointer gradients_new =
    DiffusionImageType::GradientDirectionContainerType::New();
  typename DiffusionImageType::GradientDirectionType bzero_vector;
  bzero_vector.fill(0);

  // compose the direction vector
  //  - no direction for the first image
  //  - correct ordering of the directions based on the index list
  gradients_new->push_back( bzero_vector );

  typename SplitFilterType::IndexListType index_list = split_filter->GetIndexList();
  typename SplitFilterType::IndexListType::const_iterator lIter = index_list.begin();

  while( lIter != index_list.end() )
  {
    gradients_new->push_back( gradients->at( *lIter ) );
    ++lIter;
  }

  typename mitk::ImageToDiffusionImageSource< DiffusionPixelType >::Pointer caster =
    mitk::ImageToDiffusionImageSource< DiffusionPixelType >::New();

  caster->SetImage( registeredWeighted );
  caster->SetBValue( input->GetB_Value() );
  caster->SetGradientDirections( gradients_new.GetPointer() );

  try
  {
    caster->Update();
  }
  catch( const itk::ExceptionObject& e)
  {
    m_IsInValidState = false;
    MITK_ERROR << "Casting back to diffusion image failed: ";
    mitkThrow() << "Subprocess failed with exception: " << e.what();
  }

  //
  // (5) Adapt the gradient directions according to the estimated transforms
  //
  typedef mitk::DiffusionImageCorrectionFilter< DiffusionPixelType > CorrectionFilterType;
  typename CorrectionFilterType::Pointer corrector = CorrectionFilterType::New();

  OutputImagePointerType output = caster->GetOutput();
  corrector->SetImage( output );
  corrector->CorrectDirections( estimated_transforms );

  //
  // (6) Pass the corrected image to the filters output port
  //
  m_CurrentStep += 1;
  this->GetOutput()->SetVectorImage(output->GetVectorImage());
  this->GetOutput()->SetB_Value(output->GetB_Value());
  this->GetOutput()->SetDirections(output->GetDirections());
  this->GetOutput()->SetMeasurementFrame(output->GetMeasurementFrame());
  this->GetOutput()->InitializeFromVectorImage();

  this->GetOutput()->Modified();
}

#endif // MITKDIFFUSIONIMAGETODIFFUSIONIMAGEFILTER_CPP<commit_msg>Added missing init of the expanded geometry<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#ifndef MITKDIFFUSIONIMAGETODIFFUSIONIMAGEFILTER_CPP
#define MITKDIFFUSIONIMAGETODIFFUSIONIMAGEFILTER_CPP

#include "mitkDWIHeadMotionCorrectionFilter.h"

#include "itkSplitDWImageFilter.h"
#include "itkB0ImageExtractionToSeparateImageFilter.h"

#include "mitkImageTimeSelector.h"

#include "mitkPyramidImageRegistrationMethod.h"
#include "mitkImageToDiffusionImageSource.h"

#include "mitkDiffusionImageCorrectionFilter.h"

#include <vector>

#include "mitkIOUtil.h"
#include <itkImage.h>

template< typename DiffusionPixelType>
mitk::DWIHeadMotionCorrectionFilter<DiffusionPixelType>
  ::DWIHeadMotionCorrectionFilter():
m_CurrentStep(0),
  m_Steps(100),
  m_IsInValidState(true),
  m_AbortRegistration(false)
{

}

template< typename DiffusionPixelType>
void mitk::DWIHeadMotionCorrectionFilter<DiffusionPixelType>
  ::GenerateData()
{
  typedef itk::SplitDWImageFilter< DiffusionPixelType, DiffusionPixelType> SplitFilterType;

  DiffusionImageType* input = const_cast<DiffusionImageType*>(this->GetInput(0));

  unsigned int numberOfSteps = input->GetVectorImage()->GetNumberOfComponentsPerPixel () ;
  m_Steps = numberOfSteps;
  //
  //  (1) Extract the b-zero images to a 3d+t image, register them by NCorr metric and
  //     rigid registration : they will then be used are reference image for registering
  //     the gradient images
  //
  typedef itk::B0ImageExtractionToSeparateImageFilter< DiffusionPixelType, DiffusionPixelType> B0ExtractorType;
  typename B0ExtractorType::Pointer b0_extractor = B0ExtractorType::New();
  b0_extractor->SetInput( input->GetVectorImage() );
  b0_extractor->SetDirections( input->GetDirections() );
  b0_extractor->Update();

  mitk::Image::Pointer b0Image = mitk::Image::New();
  b0Image->InitializeByItk( b0_extractor->GetOutput() );
  b0Image->SetImportChannel( b0_extractor->GetOutput()->GetBufferPointer(),
    mitk::Image::CopyMemory );

  // (2.1) Use the extractor to access the extracted b0 volumes
  mitk::ImageTimeSelector::Pointer t_selector =
    mitk::ImageTimeSelector::New();

  t_selector->SetInput( b0Image );
  t_selector->SetTimeNr(0);
  t_selector->Update();

  // first unweighted image as reference space for the registration
  mitk::Image::Pointer b0referenceImage = t_selector->GetOutput();

  mitk::PyramidImageRegistrationMethod::Pointer registrationMethod = mitk::PyramidImageRegistrationMethod::New();
  registrationMethod->SetFixedImage( b0referenceImage );
  registrationMethod->SetTransformToRigid();

  // the unweighted images are of same modality
  registrationMethod->SetCrossModalityOff();

  // use the advanced (windowed sinc) interpolation
  registrationMethod->SetUseAdvancedInterpolation(true);

  // Initialize the temporary output image
  mitk::Image::Pointer registeredB0Image = b0Image->Clone();
  const unsigned int numberOfb0Images = b0Image->GetTimeSteps();

  if( numberOfb0Images > 1)
  {
    mitk::ImageTimeSelector::Pointer t_selector2 =
      mitk::ImageTimeSelector::New();

    t_selector2->SetInput( b0Image );

    for( unsigned int i=1; i<numberOfb0Images; i++)
    {

      m_CurrentStep = i + 1;
      if( m_AbortRegistration == true) {
        m_IsInValidState = false;
        mitkThrow() << "Stopped by user.";
      };

      t_selector2->SetTimeNr(i);
      t_selector2->Update();

      registrationMethod->SetMovingImage( t_selector2->GetOutput() );

      try
      {
        MITK_INFO << " === (" << i <<"/"<< numberOfb0Images-1 << ") :: Starting registration";
        registrationMethod->Update();
      }
      catch( const itk::ExceptionObject& e)
      {
        m_IsInValidState = false;
        mitkThrow() << "Failed to register the b0 images, the PyramidRegistration threw an exception: \n" << e.what();
      }

      // import volume to the inter-results
      registeredB0Image->SetImportVolume( registrationMethod->GetResampledMovingImage()->GetData(),
        i, 0, mitk::Image::ReferenceMemory );

    }

    // use the accumulateImageFilter as provided by the ItkAccumulateFilter method in the header file
    AccessFixedDimensionByItk_1(registeredB0Image, ItkAccumulateFilter, (4), b0referenceImage );

  }

  //
  // (2) Split the diffusion image into a 3d+t regular image, extract only the weighted images
  //
  typename SplitFilterType::Pointer split_filter = SplitFilterType::New();
  split_filter->SetInput (input->GetVectorImage() );
  split_filter->SetExtractAllAboveThreshold(20, input->GetB_ValueMap() );

  try
  {
    split_filter->Update();
  }
  catch( const itk::ExceptionObject &e)
  {
    m_IsInValidState = false;
    mitkThrow() << " Caught exception from SplitImageFilter : " << e.what();
  }

  mitk::Image::Pointer splittedImage = mitk::Image::New();
  splittedImage->InitializeByItk( split_filter->GetOutput() );
  splittedImage->SetImportChannel( split_filter->GetOutput()->GetBufferPointer(),
    mitk::Image::CopyMemory );

  //
  // (3) Use again the time-selector to access the components separately in order
  //     to perform the registration of  Image -> unweighted reference
  //

  mitk::PyramidImageRegistrationMethod::Pointer weightedRegistrationMethod
    = mitk::PyramidImageRegistrationMethod::New();

  weightedRegistrationMethod->SetTransformToAffine();
  weightedRegistrationMethod->SetCrossModalityOn();

  //
  //   - (3.1) Set the reference image
  //      - a single b0 image
  //      - average over the registered b0 images if multiple present
  //
  weightedRegistrationMethod->SetFixedImage( b0referenceImage );
  // use the advanced (windowed sinc) interpolation
  weightedRegistrationMethod->SetUseAdvancedInterpolation(true);

  //
  //   - (3.2) Register all timesteps in the splitted image onto the first reference
  //
  unsigned int maxImageIdx = splittedImage->GetTimeSteps();
  mitk::TimeGeometry* tsg = splittedImage->GetTimeGeometry();
  mitk::ProportionalTimeGeometry* ptg = dynamic_cast<ProportionalTimeGeometry*>(tsg);
  ptg->Expand(maxImageIdx+1);
  ptg->SetTimeStepGeometry( ptg->GetGeometryForTimeStep(0), 6 );

  mitk::Image::Pointer registeredWeighted = mitk::Image::New();
  registeredWeighted->Initialize( splittedImage->GetPixelType(0), *tsg );

  // insert the first unweighted reference as the first volume
  registeredWeighted->SetImportVolume( b0referenceImage->GetData(),
    0,0, mitk::Image::CopyMemory );

  // mitk::Image::Pointer registeredWeighted = splittedImage->Clone();
  // this time start at 0, we have only gradient images in the 3d+t file
  // the reference image comes form an other image
  mitk::ImageTimeSelector::Pointer t_selector_w =
    mitk::ImageTimeSelector::New();

  t_selector_w->SetInput( splittedImage );

  // store the rotation parts of the transformations in a vector
  typedef mitk::PyramidImageRegistrationMethod::TransformMatrixType MatrixType;
  std::vector< MatrixType > estimated_transforms;

  for( unsigned int i=0; i<maxImageIdx; i++)
  {
    m_CurrentStep = numberOfb0Images + i + 1;
    if( m_AbortRegistration == true) {
      m_IsInValidState = false;
      mitkThrow() << "Stopped by user.";
    };

    t_selector_w->SetTimeNr(i);
    t_selector_w->Update();

    weightedRegistrationMethod->SetMovingImage( t_selector_w->GetOutput() );

    try
    {
      MITK_INFO << " === (" << i+1 <<"/"<< maxImageIdx << ") :: Starting registration";
      weightedRegistrationMethod->Update();
    }
    catch( const itk::ExceptionObject& e)
    {
      m_IsInValidState = false;
      mitkThrow() << "Failed to register the b0 images, the PyramidRegistration threw an exception: \n" << e.what();
    }

    // allow expansion
    registeredWeighted->SetImportVolume( weightedRegistrationMethod->GetResampledMovingImage()->GetData(),
      i+1, 0, mitk::Image::CopyMemory);

    estimated_transforms.push_back( weightedRegistrationMethod->GetLastRotationMatrix() );
  }

  //
  // (4) Cast the resulting image back to an diffusion weighted image
  //
  typename DiffusionImageType::GradientDirectionContainerType *gradients = input->GetDirections();
  typename DiffusionImageType::GradientDirectionContainerType::Pointer gradients_new =
    DiffusionImageType::GradientDirectionContainerType::New();
  typename DiffusionImageType::GradientDirectionType bzero_vector;
  bzero_vector.fill(0);

  // compose the direction vector
  //  - no direction for the first image
  //  - correct ordering of the directions based on the index list
  gradients_new->push_back( bzero_vector );

  typename SplitFilterType::IndexListType index_list = split_filter->GetIndexList();
  typename SplitFilterType::IndexListType::const_iterator lIter = index_list.begin();

  while( lIter != index_list.end() )
  {
    gradients_new->push_back( gradients->at( *lIter ) );
    ++lIter;
  }

  typename mitk::ImageToDiffusionImageSource< DiffusionPixelType >::Pointer caster =
    mitk::ImageToDiffusionImageSource< DiffusionPixelType >::New();

  caster->SetImage( registeredWeighted );
  caster->SetBValue( input->GetB_Value() );
  caster->SetGradientDirections( gradients_new.GetPointer() );

  try
  {
    caster->Update();
  }
  catch( const itk::ExceptionObject& e)
  {
    m_IsInValidState = false;
    MITK_ERROR << "Casting back to diffusion image failed: ";
    mitkThrow() << "Subprocess failed with exception: " << e.what();
  }

  //
  // (5) Adapt the gradient directions according to the estimated transforms
  //
  typedef mitk::DiffusionImageCorrectionFilter< DiffusionPixelType > CorrectionFilterType;
  typename CorrectionFilterType::Pointer corrector = CorrectionFilterType::New();

  OutputImagePointerType output = caster->GetOutput();
  corrector->SetImage( output );
  corrector->CorrectDirections( estimated_transforms );

  //
  // (6) Pass the corrected image to the filters output port
  //
  m_CurrentStep += 1;
  this->GetOutput()->SetVectorImage(output->GetVectorImage());
  this->GetOutput()->SetB_Value(output->GetB_Value());
  this->GetOutput()->SetDirections(output->GetDirections());
  this->GetOutput()->SetMeasurementFrame(output->GetMeasurementFrame());
  this->GetOutput()->InitializeFromVectorImage();

  this->GetOutput()->Modified();
}

#endif // MITKDIFFUSIONIMAGETODIFFUSIONIMAGEFILTER_CPP
<|endoftext|>


<commit_before><commit_msg>Create 1255 - Substring Frequency.cpp<commit_after><|endoftext|>