<commit_before>// $Id$
//**************************************************************************
//* This file is property of and copyright by the ALICE HLT Project        *
//* ALICE Experiment at CERN, All rights reserved.                         *
//*                                                                        *
//* Primary Authors: Gaute Ovrebekk <ovrebekk@ift.uib.no>                  *
//*                  for The ALICE HLT Project.                            *
//*                                                                        *
//* Permission to use, copy, modify and distribute this software and its   *
//* documentation strictly for non-commercial purposes is hereby granted   *
//* without fee, provided that the above copyright notice appears in all   *
//* copies and that both the copyright notice and this permission notice   *
//* appear in the supporting documentation. The authors make no claims     *
//* about the suitability of this software for any purpose. It is          *
//* provided "as is" without express or implied warranty.                  *
//**************************************************************************

/** @file   AliHLTITSClusterHistoComponent.cxx
    @author Gaute Ovrebekk
    @brief  Component for ploting charge in clusters
*/

#if __GNUC__>= 3
using namespace std;
#endif

#include "AliHLTITSClusterHistoComponent.h"
#include "AliHLTITSClusterDataFormat.h"
#include "AliCDBEntry.h"
#include "AliCDBManager.h"
#include "AliITSRecPoint.h"
#include "TMath.h"
#include <TFile.h>
#include <TString.h>
#include "TObjString.h"
#include "TObjArray.h"

//#include <stdlib.h>
//#include <cerrno>

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTITSClusterHistoComponent)

AliHLTITSClusterHistoComponent::AliHLTITSClusterHistoComponent()
:
fXY(NULL),
  fPhieta(NULL),
  fCharge(NULL),
  fPlotCharge(kFALSE),
  fPlotXYPhiEta(kTRUE)
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt

}

AliHLTITSClusterHistoComponent::~AliHLTITSClusterHistoComponent()
{
  // see header file for class documentation
}

// Public functions to implement AliHLTComponent's interface.
// These functions are required for the registration process

const char* AliHLTITSClusterHistoComponent::GetComponentID()
{
  // see header file for class documentation

  return "ITSClusterHisto";
}

void AliHLTITSClusterHistoComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list)
{
  // see header file for class documentation
  list.clear();
  list.push_back( kAliHLTDataTypeClusters|kAliHLTDataOriginITSSPD );
  list.push_back( kAliHLTDataTypeClusters|kAliHLTDataOriginITSSDD );
  list.push_back( kAliHLTDataTypeClusters|kAliHLTDataOriginITSSSD );
}

AliHLTComponentDataType AliHLTITSClusterHistoComponent::GetOutputDataType()
{
  // see header file for class documentation
  return kAliHLTDataTypeHistogram;

}

void AliHLTITSClusterHistoComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
{
  // see header file for class documentation
  // XXX TODO: Find more realistic values.
  constBase = 80000;
  inputMultiplier = 10;
}

AliHLTComponent* AliHLTITSClusterHistoComponent::Spawn()
{
  // see header file for class documentation
  return new AliHLTITSClusterHistoComponent;
}

int AliHLTITSClusterHistoComponent::DoInit( int argc, const char** argv )
{
  fPlotCharge=kFALSE;
  fPlotXYPhiEta=kTRUE;

  if(fPlotCharge){fCharge = new TH1F("fCharge","Total Charge of clusters",2000,0,2000);}
  if(fPlotXYPhiEta){
	fXY = new TH2F("fXY","Global XY of ITS clusters",1600,-80,80,1600,-80,80);
  	Char_t name[50];
	Char_t title[50];
	fPhieta = new TH2F*[6];
	for (Int_t iLay=0;iLay<6;iLay++) {
		sprintf(name,"Phi_vs_Eta_ITS_Layer%d",iLay+1);
		sprintf(title,"Phi vs Eta - ITS Layer %d",iLay+1);
		fPhieta[iLay]=new TH2F(name,title,60,-1.5,1.5,60,0.,2*TMath::Pi());
		fPhieta[iLay]->GetXaxis()->SetTitle("Pseudorapidity");
		fPhieta[iLay]->GetYaxis()->SetTitle("#varphi [rad]");
 	}

  }

  int iResult=0;
  TString configuration="";
  TString argument="";
  for (int i=0; i<argc && iResult>=0; i++) {
    argument=argv[i];
    if (!configuration.IsNull()) configuration+=" ";
    configuration+=argument;
  }

  if (!configuration.IsNull()) {
    iResult=Configure(configuration.Data());
  }

  return iResult;
}

int AliHLTITSClusterHistoComponent::DoDeinit()
{
  // see header file for class documentation
  if(fCharge!=NULL) delete fCharge;
  if(fXY!=NULL) {
	delete fXY;
	for(Int_t i=0;i<6;i++) delete fPhieta[5-i];
  }
  return 0;
}

int AliHLTITSClusterHistoComponent::DoEvent(const AliHLTComponentEventData& /*evtData*/, AliHLTComponentTriggerData& /*trigData*/)
{

  static Int_t event = 0;
  event++;
  int TotalSpacePoint = 0;

  const AliHLTComponentBlockData* iter = NULL;

  if(!IsDataEvent())
    return 0;

  for ( iter = GetFirstInputBlock(kAliHLTDataTypeClusters); iter != NULL; iter = GetNextInputBlock() ) {

    if(iter->fDataType!=(kAliHLTAnyDataType|kAliHLTDataOriginITSSPD) &&
       iter->fDataType!=(kAliHLTAnyDataType|kAliHLTDataOriginITSSDD) &&
       iter->fDataType!=(kAliHLTAnyDataType|kAliHLTDataOriginITSSSD))
       continue;

    const AliHLTITSClusterData* clusterData = (const AliHLTITSClusterData*) iter->fPtr;
    Int_t nSpacepoint = (Int_t) clusterData->fSpacePointCnt;
    TotalSpacePoint += nSpacepoint;
    AliHLTITSSpacePointData *clusters = (AliHLTITSSpacePointData*) clusterData->fSpacePoints;

    for(int i=0;i<nSpacepoint;i++){
      Int_t lab[4]={0,0,0,0};
      Float_t hit[6]={0,0,0,0,0,0};
      Int_t info[3]={0,0,0};

      lab[0]=clusters[i].fTracks[0];
      lab[1]=clusters[i].fTracks[1];
      lab[2]=clusters[i].fTracks[2];
      lab[3]=clusters[i].fIndex;
      hit[0]=clusters[i].fY;
      hit[1]=clusters[i].fZ;
      hit[2]=clusters[i].fSigmaY2;
      hit[3]=clusters[i].fSigmaZ2;
      hit[4]=clusters[i].fQ;
      hit[5]=clusters[i].fSigmaYZ;
      info[0]=clusters[i].fNy;
      info[1]=clusters[i].fNz;
      info[2]=clusters[i].fLayer;

      Float_t xyz[3];
      AliITSRecPoint recpoint(lab,hit,info);
      recpoint.GetGlobalXYZ(xyz);
	  Int_t layer = recpoint.GetLayer();
      if(fPlotXYPhiEta){
		fXY->Fill(xyz[0],xyz[1]);
		Float_t rad=TMath::Sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]);
		Float_t theta=TMath::ATan2(rad,xyz[2]);
		Float_t eta=-1*TMath::Log(TMath::Tan(theta/2.0));
		Float_t phi=TMath::ATan2(xyz[1],xyz[0]);
		if(phi<0.0){phi=2 * TMath::Pi() - TMath::Abs(phi);}
		fPhieta[layer]->Fill(eta,phi);
      }
      if(fPlotCharge){
		fCharge->Fill(recpoint.GetQ());
      }
    }
  }

  if(fPlotCharge){
    AliHLTUInt32_t fSpecification = 0x0;
    PushBack( (TObject*) fCharge,kAliHLTDataTypeHistogram,fSpecification);
  }
  if(fPlotXYPhiEta){
    AliHLTUInt32_t fSpecification = 0x0;
    PushBack( (TObject*) fXY,kAliHLTDataTypeHistogram,fSpecification);
	for(Int_t ii=0;ii<6;ii++)
		PushBack( (TObject*) fPhieta[ii],kAliHLTDataTypeHistogram,fSpecification);
  }

  HLTInfo("ITSClusterHisto found %d Total Spacepoints", TotalSpacePoint);

  return 0;
}

int AliHLTITSClusterHistoComponent::Configure(const char* arguments)
{

  int iResult=0;

  if (!arguments) return iResult;

  TString allArgs=arguments;
  TString argument;

  TObjArray* pTokens=allArgs.Tokenize(" ");

  if (pTokens) {
    for (int i=0; i<pTokens->GetEntries() && iResult>=0; i++) {
      argument=((TObjString*)pTokens->At(i))->GetString();
      if (argument.IsNull()) continue;

      if (argument.CompareTo("-plot-all")==0) {
	HLTInfo("Ploting all historgams");
	fPlotXYPhiEta = kTRUE;
	fPlotCharge = kTRUE;
	continue;
      }

      else if (argument.CompareTo("-plot-xy")==0) {
	HLTInfo("Ploting Global XY");
	fPlotXYPhiEta = kTRUE;
	continue;
      }

      else if (argument.CompareTo("-plot-charge")==0) {
	HLTInfo("Ploting charge of clusters");
	fPlotCharge = kTRUE;
	continue;
      }

      else {
	HLTError("unknown argument %s", argument.Data());
	iResult=-EINVAL;
	break;
      }
    }
    delete pTokens;
  }

  if(!fCharge && fPlotCharge){fCharge = new TH1F("fCharge","Total Charge of clusters",2000,0,2000);}
  if(!fXY && fPlotXYPhiEta){
	fXY = new TH2F("fXY","Global XY of ITS clusters",1600,-80,80,1600,-80,80);
  	Char_t name[50];
	Char_t title[50];
	fPhieta = new TH2F*[6];
	for (Int_t iLay=0;iLay<6;iLay++) {
		sprintf(name,"Phi_vs_Eta_ITS_Layer%d",iLay+1);
		sprintf(title,"Phi vs Eta - ITS Layer %d",iLay+1);
		fPhieta[iLay]=new TH2F(name,title,30,-1.5,1.5,200,0.,2*TMath::Pi());
		fPhieta[iLay]->GetXaxis()->SetTitle("Pseudorapidity");
		fPhieta[iLay]->GetYaxis()->SetTitle("#varphi [rad]");
 	}
  }

  return iResult;
}

int AliHLTITSClusterHistoComponent::Reconfigure(const char* cdbEntry, const char* chainId)
{
  // see header file for class documentation
  int iResult=0;

  const char* path="HLT/ConfigITS/HistoComponent";
  const char* defaultNotify="";
  if (cdbEntry) {
    path=cdbEntry;
    defaultNotify=" (default)";
  }
  if (path) {
    HLTInfo("reconfigure from entry %s%s, chain id %s", path, defaultNotify,(chainId!=NULL && chainId[0]!=0)?chainId:"<none>");
    AliCDBEntry *pEntry = AliCDBManager::Instance()->Get(path);
    if (pEntry) {
      TObjString* pString=dynamic_cast<TObjString*>(pEntry->GetObject());
      if (pString) {
	HLTInfo("received configuration object string: \'%s\'", pString->GetString().Data());
	iResult=Configure(pString->GetString().Data());
      } else {
	HLTError("configuration object \"%s\" has wrong type, required TObjString", path);
      }
    } else {
      HLTError("can not fetch object \"%s\" from CDB", path);
    }
  }

  return iResult;
}
<commit_msg>- add geometry initialization for translating the ITS clusters from local to global coordinates - add detector origin for the data blocks pushed back in HLT<commit_after>// $Id$
//**************************************************************************
//* This file is property of and copyright by the ALICE HLT Project        *
//* ALICE Experiment at CERN, All rights reserved.                         *
//*                                                                        *
//* Primary Authors: Gaute Ovrebekk <ovrebekk@ift.uib.no>                  *
//*                  for The ALICE HLT Project.                            *
//*                                                                        *
//* Permission to use, copy, modify and distribute this software and its   *
//* documentation strictly for non-commercial purposes is hereby granted   *
//* without fee, provided that the above copyright notice appears in all   *
//* copies and that both the copyright notice and this permission notice   *
//* appear in the supporting documentation. The authors make no claims     *
//* about the suitability of this software for any purpose. It is          *
//* provided "as is" without express or implied warranty.                  *
//**************************************************************************

/** @file   AliHLTITSClusterHistoComponent.cxx
    @author Gaute Ovrebekk
    @brief  Component for plotting charge in clusters
*/

#if __GNUC__>= 3
using namespace std;
#endif

#include "AliHLTITSClusterHistoComponent.h"
#include "AliHLTITSClusterDataFormat.h"
#include "AliCDBEntry.h"
#include "AliCDBManager.h"
#include "AliGeomManager.h"
#include "AliITSRecPoint.h"
#include "TMath.h"
#include <TFile.h>
#include <TString.h>
#include "TObjString.h"
#include "TObjArray.h"

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTITSClusterHistoComponent)

AliHLTITSClusterHistoComponent::AliHLTITSClusterHistoComponent()
  :
  fXY(NULL),
  fPhieta(NULL),
  fCharge(NULL),
  fPlotCharge(kFALSE),
  fPlotXYPhiEta(kTRUE)
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

AliHLTITSClusterHistoComponent::~AliHLTITSClusterHistoComponent(){
  // see header file for class documentation
}

// Public functions to implement AliHLTComponent's interface.
// These functions are required for the registration process

const char* AliHLTITSClusterHistoComponent::GetComponentID(){
  // see header file for class documentation
  return "ITSClusterHisto";
}

void AliHLTITSClusterHistoComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list){
  // see header file for class documentation
  list.clear();
  list.push_back( kAliHLTDataTypeClusters|kAliHLTDataOriginITSSPD );
  list.push_back( kAliHLTDataTypeClusters|kAliHLTDataOriginITSSDD );
  list.push_back( kAliHLTDataTypeClusters|kAliHLTDataOriginITSSSD );
}

AliHLTComponentDataType AliHLTITSClusterHistoComponent::GetOutputDataType(){
  // see header file for class documentation
  return kAliHLTDataTypeHistogram;
}

void AliHLTITSClusterHistoComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier ){
  // see header file for class documentation
  // XXX TODO: Find more realistic values.
  constBase = 5000;
  inputMultiplier = 2;
}

AliHLTComponent* AliHLTITSClusterHistoComponent::Spawn(){
  // see header file for class documentation
  return new AliHLTITSClusterHistoComponent;
}

int AliHLTITSClusterHistoComponent::DoInit( int argc, const char** argv ){
  // see header file for class documentation

  if(AliGeomManager::GetGeometry()==NULL){
    AliGeomManager::LoadGeometry();
  }

  fPlotCharge   = kFALSE;
  fPlotXYPhiEta = kTRUE;

  if(fPlotCharge) fCharge = new TH1F("fCharge","Total Charge of clusters",2000,0,2000);
  if(fPlotXYPhiEta){
     fXY = new TH2F("fXY","Global XY of ITS clusters",1600,-80,80,1600,-80,80);
     Char_t name[50];
     Char_t title[50];
     fPhieta = new TH2F*[6];
     for (Int_t iLay=0;iLay<6;iLay++){
     	     sprintf(name,"Phi_vs_Eta_ITS_Layer%d",iLay+1);
     	     sprintf(title,"Phi vs Eta - ITS Layer %d",iLay+1);
     	     fPhieta[iLay]=new TH2F(name,title,60,-1.5,1.5,60,0.,2*TMath::Pi());
     	     fPhieta[iLay]->GetXaxis()->SetTitle("Pseudorapidity");
     	     fPhieta[iLay]->GetYaxis()->SetTitle("#varphi [rad]");
     }
  }

  int iResult=0;
  TString configuration="";
  TString argument="";

  for(int i=0; i<argc && iResult>=0; i++){
    argument=argv[i];
    if (!configuration.IsNull()) configuration+=" ";
    configuration+=argument;
  }

  if(!configuration.IsNull()){
    iResult=Configure(configuration.Data());
  }

  return iResult;
}

int AliHLTITSClusterHistoComponent::DoDeinit(){
  // see header file for class documentation
  if(fCharge!=NULL) delete fCharge;
  if(fXY!=NULL) {
     delete fXY;
     for(Int_t i=0;i<6;i++) delete fPhieta[5-i];
  }
  return 0;
}

int AliHLTITSClusterHistoComponent::DoEvent(const AliHLTComponentEventData& /*evtData*/, AliHLTComponentTriggerData& /*trigData*/){
  // see header file for class documentation

  static Int_t event = 0;
  event++;
  int TotalSpacePoint = 0;

  const AliHLTComponentBlockData* iter = NULL;

  if(!IsDataEvent()) return 0;

  for(iter = GetFirstInputBlock(kAliHLTDataTypeClusters); iter != NULL; iter = GetNextInputBlock()){

      if(iter->fDataType!=(kAliHLTAnyDataType|kAliHLTDataOriginITSSPD) &&
         iter->fDataType!=(kAliHLTAnyDataType|kAliHLTDataOriginITSSDD) &&
         iter->fDataType!=(kAliHLTAnyDataType|kAliHLTDataOriginITSSSD))
         continue;

      const AliHLTITSClusterData* clusterData = (const AliHLTITSClusterData*) iter->fPtr;
      Int_t nSpacepoint = (Int_t) clusterData->fSpacePointCnt;
      TotalSpacePoint += nSpacepoint;
      AliHLTITSSpacePointData *clusters = (AliHLTITSSpacePointData*) clusterData->fSpacePoints;

      for(int i=0;i<nSpacepoint;i++){

	  Int_t lab[4]   = {0,0,0,0};
          Float_t hit[6] = {0,0,0,0,0,0};
          Int_t info[3]  = {0,0,0};

          lab[0]  = clusters[i].fTracks[0];
          lab[1]  = clusters[i].fTracks[1];
          lab[2]  = clusters[i].fTracks[2];
          lab[3]  = clusters[i].fIndex;
          hit[0]  = clusters[i].fY;
          hit[1]  = clusters[i].fZ;
          hit[2]  = clusters[i].fSigmaY2;
          hit[3]  = clusters[i].fSigmaZ2;
          hit[4]  = clusters[i].fQ;
          hit[5]  = clusters[i].fSigmaYZ;
          info[0] = clusters[i].fNy;
          info[1] = clusters[i].fNz;
          info[2] = clusters[i].fLayer;

          Float_t xyz[3];
          AliITSRecPoint recpoint(lab,hit,info);
          recpoint.GetGlobalXYZ(xyz);
    	  Int_t layer = recpoint.GetLayer();

	  if(fPlotXYPhiEta){
    	     fXY->Fill(xyz[0],xyz[1]);
    	     Float_t rad=TMath::Sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]);
    	     Float_t theta=TMath::ATan2(rad,xyz[2]);
    	     Float_t eta=-1*TMath::Log(TMath::Tan(theta/2.0));
    	     Float_t phi=TMath::ATan2(xyz[1],xyz[0]);
    	     if(phi<0.0){phi=2 * TMath::Pi() - TMath::Abs(phi);}
    	     fPhieta[layer]->Fill(eta,phi);
          }
          if(fPlotCharge) fCharge->Fill(recpoint.GetQ());
    }
  }

  if(fPlotCharge){
     AliHLTUInt32_t fSpecification = 0x0;
     PushBack( (TObject*) fCharge,kAliHLTDataTypeHistogram|kAliHLTDataOriginITS,fSpecification);
  }
  if(fPlotXYPhiEta){
     AliHLTUInt32_t fSpecification = 0x0;
     PushBack( (TObject*) fXY,kAliHLTDataTypeHistogram|kAliHLTDataOriginITS,fSpecification);
     for(Int_t ii=0;ii<6;ii++) PushBack( (TObject*) fPhieta[ii],kAliHLTDataTypeHistogram|kAliHLTDataOriginITS,fSpecification);
  }

  HLTDebug("ITSClusterHisto found %d Total Spacepoints", TotalSpacePoint);

  return 0;
}

int AliHLTITSClusterHistoComponent::Configure(const char* arguments){
  // see header file for class documentation

  int iResult=0;

  if (!arguments) return iResult;

  TString allArgs=arguments;
  TString argument;

  TObjArray* pTokens=allArgs.Tokenize(" ");

  if (pTokens) {
    for (int i=0; i<pTokens->GetEntries() && iResult>=0; i++) {
      argument=((TObjString*)pTokens->At(i))->GetString();
      if (argument.IsNull()) continue;

      if (argument.CompareTo("-plot-all")==0) {
	HLTInfo("Ploting all historgams");
	fPlotXYPhiEta = kTRUE;
	fPlotCharge = kTRUE;
	continue;
      }

      else if (argument.CompareTo("-plot-xy")==0) {
	HLTInfo("Ploting Global XY");
	fPlotXYPhiEta = kTRUE;
	continue;
      }

      else if (argument.CompareTo("-plot-charge")==0) {
	HLTInfo("Ploting charge of clusters");
	fPlotCharge = kTRUE;
	continue;
      }

      else {
	HLTError("unknown argument %s", argument.Data());
	iResult=-EINVAL;
	break;
      }
    }
    delete pTokens;
  }

  if(!fCharge && fPlotCharge){fCharge = new TH1F("fCharge","Total Charge of clusters",2000,0,2000);}
  if(!fXY && fPlotXYPhiEta){
	fXY = new TH2F("fXY","Global XY of ITS clusters",1600,-80,80,1600,-80,80);
  	Char_t name[50];
	Char_t title[50];
	fPhieta = new TH2F*[6];
	for (Int_t iLay=0;iLay<6;iLay++) {
		sprintf(name,"Phi_vs_Eta_ITS_Layer%d",iLay+1);
		sprintf(title,"Phi vs Eta - ITS Layer %d",iLay+1);
		fPhieta[iLay]=new TH2F(name,title,30,-1.5,1.5,200,0.,2*TMath::Pi());
		fPhieta[iLay]->GetXaxis()->SetTitle("Pseudorapidity");
		fPhieta[iLay]->GetYaxis()->SetTitle("#varphi [rad]");
 	}
  }

  return iResult;
}

int AliHLTITSClusterHistoComponent::Reconfigure(const char* cdbEntry, const char* chainId){
  // see header file for class documentation
  int iResult=0;

  const char* path="HLT/ConfigITS/HistoComponent";
  const char* defaultNotify="";
  if (cdbEntry) {
    path=cdbEntry;
    defaultNotify=" (default)";
  }
  if (path) {
    HLTInfo("reconfigure from entry %s%s, chain id %s", path, defaultNotify,(chainId!=NULL && chainId[0]!=0)?chainId:"<none>");
    AliCDBEntry *pEntry = AliCDBManager::Instance()->Get(path);
    if (pEntry) {
      TObjString* pString=dynamic_cast<TObjString*>(pEntry->GetObject());
      if (pString) {
	HLTInfo("received configuration object string: \'%s\'", pString->GetString().Data());
	iResult=Configure(pString->GetString().Data());
      } else {
	HLTError("configuration object \"%s\" has wrong type, required TObjString", path);
      }
    } else {
      HLTError("can not fetch object \"%s\" from CDB", path);
    }
  }

  return iResult;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013-2016 Alexander Saprykin <xelfium@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
 */

#ifndef PLIB_TESTS_STATIC
#  define BOOST_TEST_DYN_LINK
#endif

#define BOOST_TEST_MODULE pmem_test

#include "plib.h"

#include <string.h>

#ifdef PLIB_TESTS_STATIC
#  include <boost/test/included/unit_test.hpp>
#else
#  include <boost/test/unit_test.hpp>
#endif

BOOST_AUTO_TEST_SUITE (BOOST_TEST_MODULE)

BOOST_AUTO_TEST_CASE (pmem_general_test)
{
	PMemVTable	vtable;
	ppointer	ptr = NULL;
	pint		i;

	p_lib_init ();

	vtable.free = NULL;
	vtable.malloc = NULL;
	vtable.realloc = NULL;

	BOOST_CHECK (p_malloc (0) == NULL);
	BOOST_CHECK (p_malloc0 (0) == NULL);
	BOOST_CHECK (p_realloc (NULL, 0) == NULL);
	BOOST_CHECK (p_mem_set_vtable (NULL) == FALSE);
	BOOST_CHECK (p_mem_set_vtable (&vtable) == FALSE);
	p_free (NULL);

	/* Test memory allocation using system functions */
	ptr = p_malloc (1024);
	BOOST_REQUIRE (ptr != NULL);

	for (int i = 0; i < 1024; ++i)
		*(((pchar *) ptr) + i) = (pchar) (i % 127);

	for (int i = 0; i < 1024; ++i)
		BOOST_CHECK (*(((pchar *) ptr) + i) == (pchar) (i % 127));

	p_free (ptr);

	ptr = p_malloc0 (2048);
	BOOST_REQUIRE (ptr != NULL);

	for (int i = 0; i < 2048; ++i)
		BOOST_CHECK (*(((pchar *) ptr) + i) == 0);

	for (int i = 0; i < 2048; ++i)
		*(((pchar *) ptr) + i) = (pchar) (i % 127);

	for (int i = 0; i < 2048; ++i)
		BOOST_CHECK (*(((pchar *) ptr) + i) == (pchar) (i % 127));

	p_free (ptr);

	ptr = p_realloc (NULL, 1024);
	BOOST_REQUIRE (ptr != NULL);

	for (int i = 0; i < 1024; ++i)
		*(((pchar *) ptr) + i) = (pchar) (i % 127);

	ptr = p_realloc (ptr, 2048);

	for (int i = 1024; i < 2048; ++i)
		*(((pchar *) ptr) + i) = (pchar) ((i - 1) % 127);

	for (int i = 0; i < 1024; ++i)
		BOOST_CHECK (*(((pchar *) ptr) + i) == (pchar) (i % 127));

	for (int i = 1024; i < 2048; ++i)
		BOOST_CHECK (*(((pchar *) ptr) + i) == (pchar) ((i - 1) % 127));

	p_free (ptr);

	/* Test memory mapping */
	ptr = p_mem_mmap (0, NULL);
	BOOST_CHECK (ptr == NULL);

	ptr = p_mem_mmap (1024, NULL);
	BOOST_REQUIRE (ptr != NULL);

	for (i = 0; i < 1024; ++i)
		*(((pchar *) ptr) + i) = i % 127;

	for (i = 0; i < 1024; ++i)
		BOOST_CHECK (*(((pchar *) ptr) + i) == i % 127);

	BOOST_CHECK (p_mem_munmap (NULL, 1024, NULL) == FALSE);
	BOOST_CHECK (p_mem_munmap (ptr, 1024, NULL) == TRUE);

	p_lib_shutdown ();
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>tests: Add checks for memory table usage<commit_after>/*
 * Copyright (C) 2013-2016 Alexander Saprykin <xelfium@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
 */

#ifndef PLIB_TESTS_STATIC
#  define BOOST_TEST_DYN_LINK
#endif

#define BOOST_TEST_MODULE pmem_test

#include "plib.h"

#include <string.h>

#ifdef PLIB_TESTS_STATIC
#  include <boost/test/included/unit_test.hpp>
#else
#  include <boost/test/unit_test.hpp>
#endif

BOOST_AUTO_TEST_SUITE (BOOST_TEST_MODULE)

static ppointer pmem_alloc (psize nbytes)
{
	return (ppointer) malloc (nbytes);
}

static ppointer pmem_realloc (ppointer block, psize nbytes)
{
	return (ppointer) realloc (block, nbytes);
}

static void pmem_free (ppointer block)
{
	free (block);
}

BOOST_AUTO_TEST_CASE (pmem_general_test)
{
	PMemVTable	vtable;
	ppointer	ptr = NULL;
	pint		i;

	p_lib_init ();

	vtable.free	= NULL;
	vtable.malloc	= NULL;
	vtable.realloc	= NULL;

	BOOST_CHECK (p_malloc (0) == NULL);
	BOOST_CHECK (p_malloc0 (0) == NULL);
	BOOST_CHECK (p_realloc (NULL, 0) == NULL);
	BOOST_CHECK (p_mem_set_vtable (NULL) == FALSE);
	BOOST_CHECK (p_mem_set_vtable (&vtable) == FALSE);
	p_free (NULL);

	vtable.free	= pmem_free;
	vtable.malloc	= pmem_alloc;
	vtable.realloc	= pmem_realloc;

	BOOST_CHECK (p_mem_set_vtable (&vtable) == TRUE);

	/* Test memory allocation using system functions */
	ptr = p_malloc (1024);
	BOOST_REQUIRE (ptr != NULL);

	for (int i = 0; i < 1024; ++i)
		*(((pchar *) ptr) + i) = (pchar) (i % 127);

	for (int i = 0; i < 1024; ++i)
		BOOST_CHECK (*(((pchar *) ptr) + i) == (pchar) (i % 127));

	p_free (ptr);

	ptr = p_malloc0 (2048);
	BOOST_REQUIRE (ptr != NULL);

	for (int i = 0; i < 2048; ++i)
		BOOST_CHECK (*(((pchar *) ptr) + i) == 0);

	for (int i = 0; i < 2048; ++i)
		*(((pchar *) ptr) + i) = (pchar) (i % 127);

	for (int i = 0; i < 2048; ++i)
		BOOST_CHECK (*(((pchar *) ptr) + i) == (pchar) (i % 127));

	p_free (ptr);

	ptr = p_realloc (NULL, 1024);
	BOOST_REQUIRE (ptr != NULL);

	for (int i = 0; i < 1024; ++i)
		*(((pchar *) ptr) + i) = (pchar) (i % 127);

	ptr = p_realloc (ptr, 2048);

	for (int i = 1024; i < 2048; ++i)
		*(((pchar *) ptr) + i) = (pchar) ((i - 1) % 127);

	for (int i = 0; i < 1024; ++i)
		BOOST_CHECK (*(((pchar *) ptr) + i) == (pchar) (i % 127));

	for (int i = 1024; i < 2048; ++i)
		BOOST_CHECK (*(((pchar *) ptr) + i) == (pchar) ((i - 1) % 127));

	p_free (ptr);

	vtable.malloc	= (ppointer (*)(psize)) malloc;
	vtable.realloc	= (ppointer (*)(ppointer, psize)) realloc;
	vtable.free	= (void (*)(ppointer)) free;

	BOOST_CHECK (p_mem_set_vtable (&vtable) == TRUE);

	/* Test memory mapping */
	ptr = p_mem_mmap (0, NULL);
	BOOST_CHECK (ptr == NULL);

	ptr = p_mem_mmap (1024, NULL);
	BOOST_REQUIRE (ptr != NULL);

	for (i = 0; i < 1024; ++i)
		*(((pchar *) ptr) + i) = i % 127;

	for (i = 0; i < 1024; ++i)
		BOOST_CHECK (*(((pchar *) ptr) + i) == i % 127);

	BOOST_CHECK (p_mem_munmap (NULL, 1024, NULL) == FALSE);
	BOOST_CHECK (p_mem_munmap (ptr, 1024, NULL) == TRUE);

	p_lib_shutdown ();
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include "equations.hpp"
#include <stdexcept>

EquationPiece::EquationPiece(char op) : type(Type::Operation), operation(op) {}

EquationPiece::EquationPiece(double num) : type(Type::Number), number(num) {}

std::string Equation::doubleToString(double num) const {
	std::string doubleString = std::to_string(num);
	doubleString.erase(doubleString.find_last_not_of('0') + 1, std::string::npos);
	if (!doubleString.empty() && doubleString.back() == '.') {
		doubleString.pop_back();
	}
	return doubleString;
}

void Equation::addNumber(double num) {
	equationPieces.emplace_back(num);
}

void Equation::addOperation(char op) {
	equationPieces.emplace_back(op);
}

std::string Equation::toString() const {
	std::string equationString;
	for (auto piece : equationPieces) {
		if (piece.type == EquationPiece::Type::Number) {
			//Convert number to string and add it to the resulting string
			equationString += doubleToString(piece.number);
		} else {
			//Add operation to resulting string
			equationString += piece.operation;
		}
		equationString += ' ';
	}
	return equationString;
}

double Equation::evaluate() {
	std::stack<double> evaluationStack;
	for (auto piece : equationPieces) {
		if (piece.type == EquationPiece::Type::Number) {
			//Next thing in the equation is a number, add it to the stack
			evaluationStack.emplace(piece.number);
		} else {
			//Next thing in the equation is a operation,
			//	pop the previous 2 numbers
			if (evaluationStack.size() < 2) {
				throw std::runtime_error("Trying to evaluate equation. Failed because too few numbers exist.");
			}
			double num1 = evaluationStack.top();
			evaluationStack.pop();
			double num2 = evaluationStack.top();
			evaluationStack.pop();

			//	apply the operation
			double result;
			switch (piece.operation) {
			case '+':
				result = num2+num1;
				break;
			case '-':
				result = num2-num1;
				break;
			case '*':
				result = num2*num1;
				break;
			case '/':
				if (num1 == 0) {
					throw std::runtime_error("Trying to divide by 0.");
				}
				result = num2/num1;
				break;
			}

			//	push the result onto the stack
			evaluationStack.push(result);
		}
	}
	if (evaluationStack.size() != 1) {
		throw std::runtime_error("Trying to evaluate equation. Failed because too few operations exist.");
	}
	return evaluationStack.top();
}

const std::vector<char> Equation::OPERATIONS = {'+','-','*','/'};

void RandomEquationBuilder::createRandomEngine() {
	std::random_device rd;
	std::vector<unsigned int> seeds;
	seeds.reserve(std::mt19937::state_size);
	for (size_t i=0; i<std::mt19937::state_size; ++i) {
		seeds.emplace_back(rd());
	}
	std::seed_seq s(seeds.begin(), seeds.end());
	eng = std::mt19937(s);
}

double RandomEquationBuilder::randomNumber() {
	std::uniform_int_distribution<int> dist(0,NUMBERS.size()-1);
	return NUMBERS[dist(eng)];
}

char RandomEquationBuilder::randomOperation() {
	std::uniform_int_distribution<int> dist(0,Equation::OPERATIONS.size()-1);
	return Equation::OPERATIONS[dist(eng)];
}

RandomEquationBuilder::RandomEquationBuilder(const std::vector<double> NUMS) : NUMBERS(NUMS) {
	createRandomEngine();
}

Equation RandomEquationBuilder::build(const int DESIRED_NUMBER_COUNT_IN_EQUATION) {
	Equation equation;
	int numberCount=0;
	int balance=0;
	std::bernoulli_distribution opOrNumDist(0.5);
	while (numberCount < DESIRED_NUMBER_COUNT_IN_EQUATION) {
		if (balance >= 2) {
			//50/50 chance to add number or operation
			if (opOrNumDist(eng)) {
				//Add operation
				equation.addOperation(randomOperation());
				--balance;
			} else {
				//Add number
				equation.addNumber(randomNumber());
				++numberCount;
				++balance;
			}
		} else {
			//Too few numbers in the equation, must add number
			equation.addNumber(randomNumber());
			++numberCount;
			++balance;
		}
	}
	while (balance > 1) {
		//Not enough operations in the equation
		equation.addOperation(randomOperation());
		--balance;
	}
	return equation;
}<commit_msg>added protection against adding unsupported operations<commit_after>#include "equations.hpp"
#include <algorithm>
#include <stdexcept>

EquationPiece::EquationPiece(char op) : type(Type::Operation), operation(op) {}

EquationPiece::EquationPiece(double num) : type(Type::Number), number(num) {}

std::string Equation::doubleToString(double num) const {
	std::string doubleString = std::to_string(num);
	doubleString.erase(doubleString.find_last_not_of('0') + 1, std::string::npos);
	if (!doubleString.empty() && doubleString.back() == '.') {
		doubleString.pop_back();
	}
	return doubleString;
}

void Equation::addNumber(double num) {
	equationPieces.emplace_back(num);
}

void Equation::addOperation(char op) {
	if (find(OPERATIONS.begin(), OPERATIONS.end(), op) == OPERATIONS.end()) {
		throw std::runtime_error(std::string("Invalid operation ")+op+" added to equation.");
	}
	equationPieces.emplace_back(op);
}

std::string Equation::toString() const {
	std::string equationString;
	for (auto piece : equationPieces) {
		if (piece.type == EquationPiece::Type::Number) {
			//Convert number to string and add it to the resulting string
			equationString += doubleToString(piece.number);
		} else {
			//Add operation to resulting string
			equationString += piece.operation;
		}
		equationString += ' ';
	}
	return equationString;
}

double Equation::evaluate() {
	std::stack<double> evaluationStack;
	for (auto piece : equationPieces) {
		if (piece.type == EquationPiece::Type::Number) {
			//Next thing in the equation is a number, add it to the stack
			evaluationStack.emplace(piece.number);
		} else {
			//Next thing in the equation is a operation,
			//	pop the previous 2 numbers
			if (evaluationStack.size() < 2) {
				throw std::runtime_error("Trying to evaluate equation. Failed because too few numbers exist.");
			}
			double num1 = evaluationStack.top();
			evaluationStack.pop();
			double num2 = evaluationStack.top();
			evaluationStack.pop();

			//	apply the operation
			double result;
			switch (piece.operation) {
			case '+':
				result = num2+num1;
				break;
			case '-':
				result = num2-num1;
				break;
			case '*':
				result = num2*num1;
				break;
			case '/':
				if (num1 == 0) {
					throw std::runtime_error("Trying to divide by 0.");
				}
				result = num2/num1;
				break;
			default:
				//Cant get here because addOperation disallows invalid operations
				break;
			}

			//	push the result onto the stack
			evaluationStack.push(result);
		}
	}
	if (evaluationStack.size() != 1) {
		throw std::runtime_error("Trying to evaluate equation. Failed because too few operations exist.");
	}
	return evaluationStack.top();
}

const std::vector<char> Equation::OPERATIONS = {'+','-','*','/'};

void RandomEquationBuilder::createRandomEngine() {
	std::random_device rd;
	std::vector<unsigned int> seeds;
	seeds.reserve(std::mt19937::state_size);
	for (size_t i=0; i<std::mt19937::state_size; ++i) {
		seeds.emplace_back(rd());
	}
	std::seed_seq s(seeds.begin(), seeds.end());
	eng = std::mt19937(s);
}

double RandomEquationBuilder::randomNumber() {
	std::uniform_int_distribution<int> dist(0,NUMBERS.size()-1);
	return NUMBERS[dist(eng)];
}

char RandomEquationBuilder::randomOperation() {
	std::uniform_int_distribution<int> dist(0,Equation::OPERATIONS.size()-1);
	return Equation::OPERATIONS[dist(eng)];
}

RandomEquationBuilder::RandomEquationBuilder(const std::vector<double> NUMS) : NUMBERS(NUMS) {
	createRandomEngine();
}

Equation RandomEquationBuilder::build(const int DESIRED_NUMBER_COUNT_IN_EQUATION) {
	Equation equation;
	int numberCount=0;
	int balance=0;
	std::bernoulli_distribution opOrNumDist(0.5);
	while (numberCount < DESIRED_NUMBER_COUNT_IN_EQUATION) {
		if (balance >= 2) {
			//50/50 chance to add number or operation
			if (opOrNumDist(eng)) {
				//Add operation
				equation.addOperation(randomOperation());
				--balance;
			} else {
				//Add number
				equation.addNumber(randomNumber());
				++numberCount;
				++balance;
			}
		} else {
			//Too few numbers in the equation, must add number
			equation.addNumber(randomNumber());
			++numberCount;
			++balance;
		}
	}
	while (balance > 1) {
		//Not enough operations in the equation
		equation.addOperation(randomOperation());
		--balance;
	}
	return equation;
}<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef __itkExtractImageFilter_hxx
#define __itkExtractImageFilter_hxx

#include "itkExtractImageFilter.h"
#include "itkImageAlgorithm.h"
#include "itkObjectFactory.h"
#include "itkProgressReporter.h"

namespace itk
{
/**
 *
 */
template< typename TInputImage, typename TOutputImage >
ExtractImageFilter< TInputImage, TOutputImage >
::ExtractImageFilter():
#ifdef ITKV3_COMPATIBILITY
  m_DirectionCollapseStrategy(DIRECTIONCOLLAPSETOGUESS)
#else
  m_DirectionCollapseStrategy(DIRECTIONCOLLAPSETOUNKOWN)
#endif
{
  Superclass::InPlaceOff();
}

/**
 *
 */
template< typename TInputImage, typename TOutputImage >
void
ExtractImageFilter< TInputImage, TOutputImage >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "ExtractionRegion: " << m_ExtractionRegion << std::endl;
  os << indent << "OutputImageRegion: " << m_OutputImageRegion << std::endl;
  os << indent << "DirectionCollapseStrategy: " << m_DirectionCollapseStrategy << std::endl;
}

template< typename TInputImage, typename TOutputImage >
void
ExtractImageFilter< TInputImage, TOutputImage >
::CallCopyOutputRegionToInputRegion(InputImageRegionType & destRegion,
                                    const OutputImageRegionType & srcRegion)
{
  ExtractImageFilterRegionCopierType extractImageRegionCopier;

  extractImageRegionCopier(destRegion, srcRegion, m_ExtractionRegion);
}

template< typename TInputImage, typename TOutputImage >
void
ExtractImageFilter< TInputImage, TOutputImage >
::SetExtractionRegion(InputImageRegionType extractRegion)
{
  m_ExtractionRegion = extractRegion;

  unsigned int         nonzeroSizeCount = 0;
  InputImageSizeType   inputSize = extractRegion.GetSize();
  OutputImageSizeType  outputSize;
  outputSize.Fill(0);
  OutputImageIndexType outputIndex;
  outputIndex.Fill(0);

  /**
   * check to see if the number of non-zero entries in the extraction region
   * matches the number of dimensions in the output image.
   */
  for ( unsigned int i = 0; i < InputImageDimension; ++i )
    {
    if ( inputSize[i] )
      {
      outputSize[nonzeroSizeCount] = inputSize[i];
      outputIndex[nonzeroSizeCount] = extractRegion.GetIndex()[i];
      nonzeroSizeCount++;
      }
    }

  if ( nonzeroSizeCount != OutputImageDimension )
    {
    itkExceptionMacro("Extraction Region not consistent with output image");
    }

  m_OutputImageRegion.SetSize(outputSize);
  m_OutputImageRegion.SetIndex(outputIndex);
  this->Modified();
}

/**
 * ExtractImageFilter can produce an image which is a different resolution
 * than its input image.  As such, ExtractImageFilter needs to provide an
 * implementation for GenerateOutputInformation() in order to inform
 * the pipeline execution model.  The original documentation of this
 * method is below.
 *
 * \sa ProcessObject::GenerateOutputInformaton()
 */
template< typename TInputImage, typename TOutputImage >
void
ExtractImageFilter< TInputImage, TOutputImage >
::GenerateOutputInformation()
{
  // do not call the superclass' implementation of this method since
  // this filter allows the input and the output to be of different dimensions

  // get pointers to the input and output
  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
  typename Superclass::InputImageConstPointer inputPtr  = this->GetInput();

  if ( !outputPtr || !inputPtr )
    {
    return;
    }

  // Set the output image size to the same value as the extraction region.
  outputPtr->SetLargestPossibleRegion(m_OutputImageRegion);

  // Set the output spacing and origin
  const ImageBase< InputImageDimension > *phyData;

  phyData =
    dynamic_cast< const ImageBase< InputImageDimension > * >( this->GetInput() );

  if ( phyData )
    {
    // Copy what we can from the image from spacing and origin of the input
    // This logic needs to be augmented with logic that select which
    // dimensions to copy

    const typename InputImageType::SpacingType &
    inputSpacing = inputPtr->GetSpacing();
    const typename InputImageType::DirectionType &
    inputDirection = inputPtr->GetDirection();
    const typename InputImageType::PointType &
    inputOrigin = inputPtr->GetOrigin();

    typename OutputImageType::SpacingType outputSpacing;
    typename OutputImageType::DirectionType outputDirection;
    typename OutputImageType::PointType outputOrigin;
    outputOrigin.Fill(0.0);

    if ( static_cast< unsigned int >( OutputImageDimension ) >
         static_cast< unsigned int >( InputImageDimension ) )
      {
      // copy the input to the output and fill the rest of the
      // output with zeros.
      for ( unsigned int i = 0; i < InputImageDimension; ++i )
        {
        outputSpacing[i] = inputSpacing[i];
        outputOrigin[i] = inputOrigin[i];
        for ( unsigned int dim = 0; dim < InputImageDimension; ++dim )
          {
          outputDirection[i][dim] = inputDirection[i][dim];
          }
        }
      for (unsigned int i=InputImageDimension; i < OutputImageDimension; ++i )
        {
        outputSpacing[i] = 1.0;
        outputOrigin[i] = 0.0;
        for ( unsigned int dim = 0; dim < InputImageDimension; ++dim )
          {
          outputDirection[i][dim] = 0.0;
          }
        outputDirection[i][i] = 1.0;
        }
      }
    else
      {
      // copy the non-collapsed part of the input spacing and origing to the
      // output
      outputDirection.SetIdentity();
      int nonZeroCount = 0;
      for ( unsigned int i = 0; i < InputImageDimension; ++i )
        {
        if ( m_ExtractionRegion.GetSize()[i] )
          {
          outputSpacing[nonZeroCount] = inputSpacing[i];
          outputOrigin[nonZeroCount] = inputOrigin[i];
          int nonZeroCount2 = 0;
          for ( unsigned int dim = 0; dim < InputImageDimension; ++dim )
            {
            if ( m_ExtractionRegion.GetSize()[dim] )
              {
              outputDirection[nonZeroCount][nonZeroCount2] =
                inputDirection[nonZeroCount][dim];
              ++nonZeroCount2;
              }
            }
          nonZeroCount++;
          }
        }
      }
    // if the filter changes from a higher to a lower dimension, or
    // if, after rebuilding the direction cosines, there's a zero
    // length cosine vector, reset the directions to identity.
    if( static_cast<int>(InputImageDimension) != static_cast<int>(OutputImageDimension) )
      {
      switch(m_DirectionCollapseStrategy)
        {
      case DIRECTIONCOLLAPSETOIDENTITY:
          {
          outputDirection.SetIdentity();
          }
        break;
      case DIRECTIONCOLLAPSETOSUBMATRIX:
          {
          if ( vnl_determinant( outputDirection.GetVnlMatrix() ) == 0.0 )
            {
            itkExceptionMacro( << "Invalid submatrix extracted for collapsed direction." );
            }
          }
        break;
      case DIRECTIONCOLLAPSETOGUESS:
          {
          if ( vnl_determinant( outputDirection.GetVnlMatrix() ) == 0.0 )
            {
            outputDirection.SetIdentity();
            }
          }
        break;
      case DIRECTIONCOLLAPSETOUNKOWN:
      default:
          {
          itkExceptionMacro( << "It is required that the strategy for collapsing the direction matrix be explicitly specified. "
            << "Set with either myfilter->SetDirectionCollapseToIdentity() or myfilter->SetDirectionCollapseToSubmatrix() "
            << typeid( ImageBase< InputImageDimension > * ).name() );
          }
        }
      }
    // set the spacing and origin
    outputPtr->SetSpacing(outputSpacing);
    outputPtr->SetDirection(outputDirection);
    outputPtr->SetOrigin(outputOrigin);
    outputPtr->SetNumberOfComponentsPerPixel(
      inputPtr->GetNumberOfComponentsPerPixel() );
    }
  else
    {
    // pointer could not be cast back down
    itkExceptionMacro( << "itk::ExtractImageFilter::GenerateOutputInformation "
                       << "cannot cast input to "
                       << typeid( ImageBase< InputImageDimension > * ).name() );
    }
}

template< typename TInputImage, typename TOutputImage >
void
ExtractImageFilter< TInputImage, TOutputImage >
::GenerateData()
{

  // InPlace::AllocateOutputs set the running in place ivar.
  // This method will be called again, by GenerateData, but there is
  // no harm done.
  this->AllocateOutputs();

  // The input matched the output, nothing to do.
  if ( this->GetRunningInPlace() )
    {
    OutputImageType *outputPtr = this->GetOutput();

    // the in-place grafting copies the meta data, this needs to be
    // set back.
    outputPtr->SetLargestPossibleRegion(m_OutputImageRegion);

    this->UpdateProgress( 1.0 );
    return;
    }

  this->Superclass::GenerateData();
}

/**
 * ExtractImageFilter can be implemented as a multithreaded filter.
 * Therefore, this implementation provides a ThreadedGenerateData()
 * routine which is called for each processing thread. The output
 * image data is allocated automatically by the superclass prior to
 * calling ThreadedGenerateData().  ThreadedGenerateData can only
 * write to the portion of the output image specified by the
 * parameter "outputRegionForThread"
 *
 * \sa ImageToImageFilter::ThreadedGenerateData(),
 *     ImageToImageFilter::GenerateData()
 */
template< typename TInputImage, typename TOutputImage >
void
ExtractImageFilter< TInputImage, TOutputImage >
::ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread,
                       ThreadIdType threadId)
{
  itkDebugMacro(<< "Actually executing");

  // Get the input and output pointers
  const InputImageType *inputPtr = this->GetInput();
  OutputImageType      *outputPtr = this->GetOutput();

  // support progress methods/callbacks
  ProgressReporter progress( this, threadId, 1 );

  // Define the portion of the input to walk for this thread
  InputImageRegionType inputRegionForThread;
  this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread);

  // copy the input pixel to the output
  ImageAlgorithm::Copy( inputPtr, outputPtr, inputRegionForThread, outputRegionForThread );
  progress.CompletedPixel();

}
} // end namespace itk

#endif
<commit_msg>BUG: ExtractImageFilter::CollapseToSubMatrix fix<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef __itkExtractImageFilter_hxx
#define __itkExtractImageFilter_hxx

#include "itkExtractImageFilter.h"
#include "itkImageAlgorithm.h"
#include "itkObjectFactory.h"
#include "itkProgressReporter.h"

namespace itk
{
/**
 *
 */
template< typename TInputImage, typename TOutputImage >
ExtractImageFilter< TInputImage, TOutputImage >
::ExtractImageFilter():
#ifdef ITKV3_COMPATIBILITY
  m_DirectionCollapseStrategy(DIRECTIONCOLLAPSETOGUESS)
#else
  m_DirectionCollapseStrategy(DIRECTIONCOLLAPSETOUNKOWN)
#endif
{
  Superclass::InPlaceOff();
}

/**
 *
 */
template< typename TInputImage, typename TOutputImage >
void
ExtractImageFilter< TInputImage, TOutputImage >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "ExtractionRegion: " << m_ExtractionRegion << std::endl;
  os << indent << "OutputImageRegion: " << m_OutputImageRegion << std::endl;
  os << indent << "DirectionCollapseStrategy: " << m_DirectionCollapseStrategy << std::endl;
}

template< typename TInputImage, typename TOutputImage >
void
ExtractImageFilter< TInputImage, TOutputImage >
::CallCopyOutputRegionToInputRegion(InputImageRegionType & destRegion,
                                    const OutputImageRegionType & srcRegion)
{
  ExtractImageFilterRegionCopierType extractImageRegionCopier;

  extractImageRegionCopier(destRegion, srcRegion, m_ExtractionRegion);
}

template< typename TInputImage, typename TOutputImage >
void
ExtractImageFilter< TInputImage, TOutputImage >
::SetExtractionRegion(InputImageRegionType extractRegion)
{
  m_ExtractionRegion = extractRegion;

  unsigned int         nonzeroSizeCount = 0;
  InputImageSizeType   inputSize = extractRegion.GetSize();
  OutputImageSizeType  outputSize;
  outputSize.Fill(0);
  OutputImageIndexType outputIndex;
  outputIndex.Fill(0);

  /**
   * check to see if the number of non-zero entries in the extraction region
   * matches the number of dimensions in the output image.
   */
  for ( unsigned int i = 0; i < InputImageDimension; ++i )
    {
    if ( inputSize[i] )
      {
      outputSize[nonzeroSizeCount] = inputSize[i];
      outputIndex[nonzeroSizeCount] = extractRegion.GetIndex()[i];
      nonzeroSizeCount++;
      }
    }

  if ( nonzeroSizeCount != OutputImageDimension )
    {
    itkExceptionMacro("Extraction Region not consistent with output image");
    }

  m_OutputImageRegion.SetSize(outputSize);
  m_OutputImageRegion.SetIndex(outputIndex);
  this->Modified();
}

/**
 * ExtractImageFilter can produce an image which is a different resolution
 * than its input image.  As such, ExtractImageFilter needs to provide an
 * implementation for GenerateOutputInformation() in order to inform
 * the pipeline execution model.  The original documentation of this
 * method is below.
 *
 * \sa ProcessObject::GenerateOutputInformaton()
 */
template< typename TInputImage, typename TOutputImage >
void
ExtractImageFilter< TInputImage, TOutputImage >
::GenerateOutputInformation()
{
  // do not call the superclass' implementation of this method since
  // this filter allows the input and the output to be of different dimensions

  // get pointers to the input and output
  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
  typename Superclass::InputImageConstPointer inputPtr  = this->GetInput();

  if ( !outputPtr || !inputPtr )
    {
    return;
    }

  // Set the output image size to the same value as the extraction region.
  outputPtr->SetLargestPossibleRegion(m_OutputImageRegion);

  // Set the output spacing and origin
  const ImageBase< InputImageDimension > *phyData;

  phyData =
    dynamic_cast< const ImageBase< InputImageDimension > * >( this->GetInput() );

  if ( phyData )
    {
    // Copy what we can from the image from spacing and origin of the input
    // This logic needs to be augmented with logic that select which
    // dimensions to copy

    const typename InputImageType::SpacingType &
    inputSpacing = inputPtr->GetSpacing();
    const typename InputImageType::DirectionType &
    inputDirection = inputPtr->GetDirection();
    const typename InputImageType::PointType &
    inputOrigin = inputPtr->GetOrigin();

    typename OutputImageType::SpacingType outputSpacing;
    typename OutputImageType::DirectionType outputDirection;
    typename OutputImageType::PointType outputOrigin;
    outputOrigin.Fill(0.0);

    if ( static_cast< unsigned int >( OutputImageDimension ) >
         static_cast< unsigned int >( InputImageDimension ) )
      {
      // copy the input to the output and fill the rest of the
      // output with zeros.
      for ( unsigned int i = 0; i < InputImageDimension; ++i )
        {
        outputSpacing[i] = inputSpacing[i];
        outputOrigin[i] = inputOrigin[i];
        for ( unsigned int dim = 0; dim < InputImageDimension; ++dim )
          {
          outputDirection[i][dim] = inputDirection[i][dim];
          }
        }
      for (unsigned int i=InputImageDimension; i < OutputImageDimension; ++i )
        {
        outputSpacing[i] = 1.0;
        outputOrigin[i] = 0.0;
        for ( unsigned int dim = 0; dim < InputImageDimension; ++dim )
          {
          outputDirection[i][dim] = 0.0;
          }
        outputDirection[i][i] = 1.0;
        }
      }
    else
      {
      // copy the non-collapsed part of the input spacing and origing to the
      // output
      outputDirection.SetIdentity();
      int nonZeroCount = 0;
      for ( unsigned int i = 0; i < InputImageDimension; ++i )
        {
        if ( m_ExtractionRegion.GetSize()[i] )
          {
          outputSpacing[nonZeroCount] = inputSpacing[i];
          outputOrigin[nonZeroCount] = inputOrigin[i];
          int nonZeroCount2 = 0;
          for ( unsigned int dim = 0; dim < InputImageDimension; ++dim )
            {
            if ( m_ExtractionRegion.GetSize()[dim] )
              {
              outputDirection[nonZeroCount][nonZeroCount2] =
                inputDirection[i][dim];
              ++nonZeroCount2;
              }
            }
          nonZeroCount++;
          }
        }
      }
    // if the filter changes from a higher to a lower dimension, or
    // if, after rebuilding the direction cosines, there's a zero
    // length cosine vector, reset the directions to identity.
    if( static_cast<int>(InputImageDimension) != static_cast<int>(OutputImageDimension) )
      {
      switch(m_DirectionCollapseStrategy)
        {
      case DIRECTIONCOLLAPSETOIDENTITY:
          {
          outputDirection.SetIdentity();
          }
        break;
      case DIRECTIONCOLLAPSETOSUBMATRIX:
          {
          if ( vnl_determinant( outputDirection.GetVnlMatrix() ) == 0.0 )
            {
            itkExceptionMacro( << "Invalid submatrix extracted for collapsed direction." );
            }
          }
        break;
      case DIRECTIONCOLLAPSETOGUESS:
          {
          if ( vnl_determinant( outputDirection.GetVnlMatrix() ) == 0.0 )
            {
            outputDirection.SetIdentity();
            }
          }
        break;
      case DIRECTIONCOLLAPSETOUNKOWN:
      default:
          {
          itkExceptionMacro( << "It is required that the strategy for collapsing the direction matrix be explicitly specified. "
            << "Set with either myfilter->SetDirectionCollapseToIdentity() or myfilter->SetDirectionCollapseToSubmatrix() "
            << typeid( ImageBase< InputImageDimension > * ).name() );
          }
        }
      }
    // set the spacing and origin
    outputPtr->SetSpacing(outputSpacing);
    outputPtr->SetDirection(outputDirection);
    outputPtr->SetOrigin(outputOrigin);
    outputPtr->SetNumberOfComponentsPerPixel(
      inputPtr->GetNumberOfComponentsPerPixel() );
    }
  else
    {
    // pointer could not be cast back down
    itkExceptionMacro( << "itk::ExtractImageFilter::GenerateOutputInformation "
                       << "cannot cast input to "
                       << typeid( ImageBase< InputImageDimension > * ).name() );
    }
}

template< typename TInputImage, typename TOutputImage >
void
ExtractImageFilter< TInputImage, TOutputImage >
::GenerateData()
{

  // InPlace::AllocateOutputs set the running in place ivar.
  // This method will be called again, by GenerateData, but there is
  // no harm done.
  this->AllocateOutputs();

  // The input matched the output, nothing to do.
  if ( this->GetRunningInPlace() )
    {
    OutputImageType *outputPtr = this->GetOutput();

    // the in-place grafting copies the meta data, this needs to be
    // set back.
    outputPtr->SetLargestPossibleRegion(m_OutputImageRegion);

    this->UpdateProgress( 1.0 );
    return;
    }

  this->Superclass::GenerateData();
}

/**
 * ExtractImageFilter can be implemented as a multithreaded filter.
 * Therefore, this implementation provides a ThreadedGenerateData()
 * routine which is called for each processing thread. The output
 * image data is allocated automatically by the superclass prior to
 * calling ThreadedGenerateData().  ThreadedGenerateData can only
 * write to the portion of the output image specified by the
 * parameter "outputRegionForThread"
 *
 * \sa ImageToImageFilter::ThreadedGenerateData(),
 *     ImageToImageFilter::GenerateData()
 */
template< typename TInputImage, typename TOutputImage >
void
ExtractImageFilter< TInputImage, TOutputImage >
::ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread,
                       ThreadIdType threadId)
{
  itkDebugMacro(<< "Actually executing");

  // Get the input and output pointers
  const InputImageType *inputPtr = this->GetInput();
  OutputImageType      *outputPtr = this->GetOutput();

  // support progress methods/callbacks
  ProgressReporter progress( this, threadId, 1 );

  // Define the portion of the input to walk for this thread
  InputImageRegionType inputRegionForThread;
  this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread);

  // copy the input pixel to the output
  ImageAlgorithm::Copy( inputPtr, outputPtr, inputRegionForThread, outputRegionForThread );
  progress.CompletedPixel();

}
} // end namespace itk

#endif
<|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.

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

#include <mitkPolhemusInterface.h>
#define _USE_MATH_DEFINES
#include <math.h>

#include <PDI.h>

BYTE  MotionBuf[0x1FA400];

mitk::PolhemusInterface::PolhemusInterface() : m_continousTracking(false)
{
  m_pdiDev = new CPDIdev();
}

mitk::PolhemusInterface::~PolhemusInterface()
{
  delete m_pdiDev;
}

bool mitk::PolhemusInterface::InitializeDevice()
{
  m_pdiDev->ResetTracker();
  m_pdiDev->ResetSAlignment(-1);
  m_pdiDev->Trace(TRUE, 7);
  m_continousTracking = false;
  return true;
}

bool mitk::PolhemusInterface::SetupDevice()
{
  m_pdiDev->SetPnoBuffer(MotionBuf, 0x1FA400);
  m_pdiDev->SetMetric(true); //use cm instead of inches

  m_pdiDev->StartPipeExport();

  CPDImdat pdiMDat;
  pdiMDat.Empty();
  pdiMDat.Append(PDI_MODATA_FRAMECOUNT);
  pdiMDat.Append(PDI_MODATA_POS);
  pdiMDat.Append(PDI_MODATA_ORI);
  m_pdiDev->SetSDataList(-1, pdiMDat);

  CPDIbiterr cBE;
  m_pdiDev->GetBITErrs(cBE);

  if (!(cBE.IsClear())) { m_pdiDev->ClearBITErrs(); }

  return true;
}

bool mitk::PolhemusInterface::StartTracking()
{
  LPCTSTR	szWindowClass = _T("PDIconsoleWinClass");
  HINSTANCE hInst = GetModuleHandle(0);
  HWND	hwnd = CreateWindowEx(
    WS_EX_NOACTIVATE,//WS_EX_STATICEDGE, //
    szWindowClass,
    _T("MyWindowName"),
    WS_POPUP,
    0, 0, 1, 1,
    HWND_MESSAGE,
    0,
    hInst,
    0);

  m_continousTracking = true;
  return m_pdiDev->StartContPno(hwnd);
}

bool mitk::PolhemusInterface::StopTracking()
{
  m_continousTracking = false;
  m_pdiDev->StopContPno();
  return true;
}

bool mitk::PolhemusInterface::Connect()
{
  if (!InitializeDevice()) { return false; }

  if (m_pdiDev->CnxReady()) { return true; }
  CPDIser	pdiSer;
  m_pdiDev->SetSerialIF(&pdiSer);

  ePiCommType eType = m_pdiDev->DiscoverCnx();
  switch (eType)
  {
  case PI_CNX_USB:
    MITK_INFO << "USB Connection: " << m_pdiDev->GetLastResultStr();
    break;
  case PI_CNX_SERIAL:
    MITK_INFO << "Serial Connection: " << m_pdiDev->GetLastResultStr();
    break;
  default:
    MITK_INFO << "DiscoverCnx result: " << m_pdiDev->GetLastResultStr();
    break;
  }

  if (!SetupDevice()) { return false; }

  return m_pdiDev->CnxReady();
}

bool mitk::PolhemusInterface::Disconnect()
{
  bool returnValue = true;
  //If Tracking is running, stop tracking first
  if (m_continousTracking)
  {
    this->StopTracking();
  }

  returnValue = m_pdiDev->Disconnect();
  MITK_INFO << "Disconnect: " << m_pdiDev->GetLastResultStr();
  return returnValue;
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::GetLastFrame()
{
  PBYTE pBuf;
  DWORD dwSize;

  //read one frame
  if (!m_pdiDev->LastPnoPtr(pBuf, dwSize)) { MITK_WARN << m_pdiDev->GetLastResultStr(); }

  std::vector<mitk::PolhemusInterface::trackingData> returnValue = ParsePolhemusRawData(pBuf, dwSize);

  if (returnValue.empty()) { MITK_WARN << "Cannot parse data / no tools present"; }

  return returnValue;
}

unsigned int mitk::PolhemusInterface::GetNumberOfTools()
{
  if (m_continousTracking) return GetLastFrame().size();
  else return GetSingleFrame().size();
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::GetSingleFrame()
{
  if (m_continousTracking)
  {
    MITK_WARN << "Cannot get a single frame when continuous tracking is on!";
    return std::vector<mitk::PolhemusInterface::trackingData>();
  }
  PBYTE pBuf;
  DWORD dwSize;

  //read one frame
  if (!m_pdiDev->ReadSinglePnoBuf(pBuf, dwSize)) {
    MITK_WARN << m_pdiDev->GetLastResultStr();
    return std::vector<mitk::PolhemusInterface::trackingData>();
  }

  return ParsePolhemusRawData(pBuf, dwSize);
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::ParsePolhemusRawData(PBYTE pBuf, DWORD dwSize)
{
  std::vector<mitk::PolhemusInterface::trackingData> returnValue;

  DWORD i = 0;

  while (i < dwSize)
  {
    BYTE ucSensor = pBuf[i + 2];
    SHORT shSize = pBuf[i + 6];

    // skip rest of header
    i += 8;

    PDWORD pFC = (PDWORD)(&pBuf[i]);
    PFLOAT pPno = (PFLOAT)(&pBuf[i + 4]);

    mitk::PolhemusInterface::trackingData currentTrackingData;

    currentTrackingData.id = ucSensor;

    currentTrackingData.pos[0] = pPno[0] * 10; //from cm to mm
    currentTrackingData.pos[1] = pPno[1] * 10;
    currentTrackingData.pos[2] = pPno[2] * 10;

    double azimuthAngle = pPno[3] / 180 * M_PI; //from degree to rad
    double elevationAngle = pPno[4] / 180 * M_PI;
    double rollAngle = pPno[5] / 180 * M_PI;
    vnl_quaternion<double> eulerQuat(rollAngle, elevationAngle, azimuthAngle);
    currentTrackingData.rot = eulerQuat;

    returnValue.push_back(currentTrackingData);
    i += shSize;
  }
  return returnValue;
}

void mitk::PolhemusInterface::SetHemisphereTrackingEnabled(bool _HeisphereTrackingEnabeled)
{
  //HemisphereTracking is switched on by SetSHeiTrack(-1). "-1" means for all sensors.
  //To switch heisphere tracking of, you need to set a hemisphere vector by calling SetSHemisphere(-1, { (float)1,0,0 })
  if (_HeisphereTrackingEnabeled)
  {
    m_pdiDev->SetSHemiTrack(-1);
  }
  else
  {
    m_pdiDev->SetSHemisphere(-1, { (float)1, 0, 0 });
    //MITK_INFO << m_pdiDev->GetLastResultStr();
  }
}

void mitk::PolhemusInterface::PrintStatus()
{
  MITK_INFO << "Polhemus status: " << this->m_pdiDev->CnxReady();
}<commit_msg>Introduce variable for return value to enable additional function calls before returning.<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.

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

#include <mitkPolhemusInterface.h>
#define _USE_MATH_DEFINES
#include <math.h>

#include <PDI.h>

BYTE  MotionBuf[0x1FA400];

mitk::PolhemusInterface::PolhemusInterface() : m_continousTracking(false)
{
  m_pdiDev = new CPDIdev();
}

mitk::PolhemusInterface::~PolhemusInterface()
{
  delete m_pdiDev;
}

bool mitk::PolhemusInterface::InitializeDevice()
{
  m_pdiDev->ResetTracker();
  m_pdiDev->ResetSAlignment(-1);
  m_pdiDev->Trace(TRUE, 7);
  m_continousTracking = false;
  return true;
}

bool mitk::PolhemusInterface::SetupDevice()
{
  m_pdiDev->SetPnoBuffer(MotionBuf, 0x1FA400);
  m_pdiDev->SetMetric(true); //use cm instead of inches

  m_pdiDev->StartPipeExport();

  CPDImdat pdiMDat;
  pdiMDat.Empty();
  pdiMDat.Append(PDI_MODATA_FRAMECOUNT);
  pdiMDat.Append(PDI_MODATA_POS);
  pdiMDat.Append(PDI_MODATA_ORI);
  m_pdiDev->SetSDataList(-1, pdiMDat);

  CPDIbiterr cBE;
  m_pdiDev->GetBITErrs(cBE);

  if (!(cBE.IsClear())) { m_pdiDev->ClearBITErrs(); }

  return true;
}

bool mitk::PolhemusInterface::StartTracking()
{
  LPCTSTR	szWindowClass = _T("PDIconsoleWinClass");
  HINSTANCE hInst = GetModuleHandle(0);
  HWND	hwnd = CreateWindowEx(
    WS_EX_NOACTIVATE,//WS_EX_STATICEDGE, //
    szWindowClass,
    _T("MyWindowName"),
    WS_POPUP,
    0, 0, 1, 1,
    HWND_MESSAGE,
    0,
    hInst,
    0);

  m_continousTracking = true;
  return m_pdiDev->StartContPno(hwnd);
}

bool mitk::PolhemusInterface::StopTracking()
{
  m_continousTracking = false;
  m_pdiDev->StopContPno();
  return true;
}

bool mitk::PolhemusInterface::Connect()
{
  bool returnValue;
  //Initialize, and if it is not successful, return false.
  if (!InitializeDevice())
  {
    returnValue = false;
  }
  //Connect
  else if (m_pdiDev->CnxReady())
  {
    returnValue = true;
  }
  //If it is not successful, search for connections.
  else
  {
    CPDIser  pdiSer;
    m_pdiDev->SetSerialIF(&pdiSer);

    ePiCommType eType = m_pdiDev->DiscoverCnx();
    switch (eType)
    {
    case PI_CNX_USB:
      MITK_INFO << "USB Connection: " << m_pdiDev->GetLastResultStr();
      break;
    case PI_CNX_SERIAL:
      MITK_INFO << "Serial Connection: " << m_pdiDev->GetLastResultStr();
      break;
    default:
      MITK_INFO << "DiscoverCnx result: " << m_pdiDev->GetLastResultStr();
      break;
    }

    //Setup device
    if (!SetupDevice())
    {
      returnValue = false;
    }
    else
    {
      returnValue = m_pdiDev->CnxReady();
    }
  }

  if (returnValue)
  {

    return true;
  }
  else
    return false;
}

bool mitk::PolhemusInterface::Disconnect()
{
  bool returnValue = true;
  //If Tracking is running, stop tracking first
  if (m_continousTracking)
  {
    this->StopTracking();
  }

  returnValue = m_pdiDev->Disconnect();
  MITK_INFO << "Disconnect: " << m_pdiDev->GetLastResultStr();
  return returnValue;
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::GetLastFrame()
{
  PBYTE pBuf;
  DWORD dwSize;

  //read one frame
  if (!m_pdiDev->LastPnoPtr(pBuf, dwSize)) { MITK_WARN << m_pdiDev->GetLastResultStr(); }

  std::vector<mitk::PolhemusInterface::trackingData> returnValue = ParsePolhemusRawData(pBuf, dwSize);

  if (returnValue.empty()) { MITK_WARN << "Cannot parse data / no tools present"; }

  return returnValue;
}

unsigned int mitk::PolhemusInterface::GetNumberOfTools()
{
  if (m_continousTracking) return GetLastFrame().size();
  else return GetSingleFrame().size();
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::GetSingleFrame()
{
  if (m_continousTracking)
  {
    MITK_WARN << "Cannot get a single frame when continuous tracking is on!";
    return std::vector<mitk::PolhemusInterface::trackingData>();
  }
  PBYTE pBuf;
  DWORD dwSize;

  //read one frame
  if (!m_pdiDev->ReadSinglePnoBuf(pBuf, dwSize)) {
    MITK_WARN << m_pdiDev->GetLastResultStr();
    return std::vector<mitk::PolhemusInterface::trackingData>();
  }

  return ParsePolhemusRawData(pBuf, dwSize);
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::ParsePolhemusRawData(PBYTE pBuf, DWORD dwSize)
{
  std::vector<mitk::PolhemusInterface::trackingData> returnValue;

  DWORD i = 0;

  while (i < dwSize)
  {
    BYTE ucSensor = pBuf[i + 2];
    SHORT shSize = pBuf[i + 6];

    // skip rest of header
    i += 8;

    PDWORD pFC = (PDWORD)(&pBuf[i]);
    PFLOAT pPno = (PFLOAT)(&pBuf[i + 4]);

    mitk::PolhemusInterface::trackingData currentTrackingData;

    currentTrackingData.id = ucSensor;

    currentTrackingData.pos[0] = pPno[0] * 10; //from cm to mm
    currentTrackingData.pos[1] = pPno[1] * 10;
    currentTrackingData.pos[2] = pPno[2] * 10;

    double azimuthAngle = pPno[3] / 180 * M_PI; //from degree to rad
    double elevationAngle = pPno[4] / 180 * M_PI;
    double rollAngle = pPno[5] / 180 * M_PI;
    vnl_quaternion<double> eulerQuat(rollAngle, elevationAngle, azimuthAngle);
    currentTrackingData.rot = eulerQuat;

    returnValue.push_back(currentTrackingData);
    i += shSize;
  }
  return returnValue;
}

void mitk::PolhemusInterface::SetHemisphereTrackingEnabled(bool _HeisphereTrackingEnabeled)
{
  //HemisphereTracking is switched on by SetSHeiTrack(-1). "-1" means for all sensors.
  //To switch heisphere tracking of, you need to set a hemisphere vector by calling SetSHemisphere(-1, { (float)1,0,0 })
  if (_HeisphereTrackingEnabeled)
  {
    m_pdiDev->SetSHemiTrack(-1);
  }
  else
  {
    m_pdiDev->SetSHemisphere(-1, { (float)1, 0, 0 });
    //MITK_INFO << m_pdiDev->GetLastResultStr();
  }
}

void mitk::PolhemusInterface::PrintStatus()
{
  MITK_INFO << "Polhemus status: " << this->m_pdiDev->CnxReady();
}<|endoftext|>


<commit_before>/**
 * DPDK bridge example application
 * =======================================
 * This application demonstrates how to create a bridge between two network devices using PcapPlusPlus DPDK APIs.
 * It listens to two DPDK ports (a.k.a DPDK devices), and forwards all the traffic received on one port to the other, acting like a L2 bridge.
 *
 * The application is very similar to [DPDK's L2 forwarding example](https://doc.dpdk.org/guides/sample_app_ug/l2_forward_real_virtual.html)
 * and demonstrates how to achieve the same functionaly with PcapPlusPlus using less and easier to understand C++ code.
 *
 * The application uses the concept of worker threads. It creates 2 worker threads running in an endless loop (as long as the app is running):
 * one for receiving packets on NIC#1 and sending them to NIC#2, and another for receiving packets on NIC#2 and sending them to NIC#1.
 *
 * __Important__:
 * - This application runs only on Linux (DPDK is not supported on Windows and Mac OS X)
 * - This application (like all applications using DPDK) should be run as 'sudo'
 * - In order to test this application you need an envorinment where the bridge is connected directly (back-to-back) to the two machines the
 *   bridge wants to connect
*/

#include "Common.h"
#include "AppWorkerThread.h"

#include "DpdkDeviceList.h"
#include "IPv4Layer.h"
#include "TcpLayer.h"
#include "UdpLayer.h"
#include "SystemUtils.h"
#include "PcapPlusPlusVersion.h"
#include "TablePrinter.h"

#include <vector>
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <signal.h>
#include <getopt.h>
#include <string>
#include <sstream>
#include <unistd.h>

using namespace pcpp;

#define COLLECT_STATS_EVERY_SEC 1
#define DEFAULT_MBUF_POOL_SIZE 4095
#define DEFAULT_QUEUE_QUANTITY 1

static struct option DpdkBridgeOptions[] =
{
	{"dpdk-ports",  required_argument, 0, 'd'},
	{"core-mask",  optional_argument, 0, 'c'},
	{"mbuf-pool-size",  optional_argument, 0, 'm'},
	{"queue-quantity",  optional_argument, 0, 'q'},
	{"help", optional_argument, 0, 'h'},
	{"list", optional_argument, 0, 'l'},
	{"version", optional_argument, 0, 'v'},
	{0, 0, 0, 0}
};

/**
 * Print application usage
 */
void printUsage()
{
	printf("\nUsage:\n"
			"------\n"
			"%s [-hlv] [-c CORE_MASK] [-m POOL_SIZE] -d PORT_1,PORT_2 [-q QUEUE_QTY]\n"
			"\nOptions:\n\n"
			"    -h|--help                                  : Displays this help message and exits\n"
			"    -l|--list                                  : Print the list of DPDK ports and exits\n"
			"    -v|--version                               : Displays the current version and exits\n"
			"    -c|--core-mask CORE_MASK                   : Core mask of cores to use. For example: use 7 (binary 0111) to use cores 0,1,2.\n"
			"                                                 Default is using all cores except management core\n"
			"    -m|--mbuf-pool-size POOL_SIZE              : DPDK mBuf pool size to initialize DPDK with. Default value is 4095\n\n", AppName::get().c_str());
			"    -d|--dpdk-ports PORT_1,PORT_2              : A comma-separated list of two DPDK port numbers to be bridged.\n"
			"                                                 To see all available DPDK ports use the -l switch\n"
			"    -q|--queue-quantity QUEUE_QTY              : Quantity of RX queues to be opened for each DPDK device. Default value is 1\n"
}

/**
 * Print application version
 */
void printAppVersion()
{
	printf("%s %s\n", AppName::get().c_str(), getPcapPlusPlusVersionFull().c_str());
	printf("Built: %s\n", getBuildDateTime().c_str());
	printf("Built from: %s\n", getGitInfo().c_str());
	exit(0);
}

/**
 * Print to console all available DPDK ports. Used by the -l switch
 */
void listDpdkPorts()
{
	CoreMask coreMaskToUse = getCoreMaskForAllMachineCores();

	// initialize DPDK
	if (!DpdkDeviceList::initDpdk(coreMaskToUse, DEFAULT_MBUF_POOL_SIZE))
	{
		EXIT_WITH_ERROR("couldn't initialize DPDK");
	}

	printf("DPDK port list:\n");

	// go over all available DPDK devices and print info for each one
	vector<DpdkDevice*> deviceList = DpdkDeviceList::getInstance().getDpdkDeviceList();
	for (vector<DpdkDevice*>::iterator iter = deviceList.begin(); iter != deviceList.end(); iter++)
	{
		DpdkDevice* dev = *iter;
		printf("    Port #%d: MAC address='%s'; PCI address='%s'; PMD='%s'; Queues='%d/%d'\n",
				dev->getDeviceId(),
				dev->getMacAddress().toString().c_str(),
				dev->getPciAddress().toString().c_str(),
				dev->getPMDName().c_str(),
				dev->getTotalNumOfRxQueues(),
				dev->getTotalNumOfTxQueues()
		);
	}
}

struct DpdkBridgeArgs
{
	bool shouldStop;
	std::vector<DpdkWorkerThread*>* workerThreadsVector;

	DpdkBridgeArgs() : shouldStop(false), workerThreadsVector(NULL) {}
};

/**
 * The callback to be called when application is terminated by ctrl-c. Do cleanup and print summary stats
 */
void onApplicationInterrupted(void* cookie)
{
	DpdkBridgeArgs* args = (DpdkBridgeArgs*)cookie;

	printf("\n\nApplication stopped\n");

	// stop worker threads
	DpdkDeviceList::getInstance().stopDpdkWorkerThreads();

	args->shouldStop = true;
}

/**
 * Extract and print traffic stats from a device
 */
void printStats(DpdkDevice* device)
{
	DpdkDevice::DpdkDeviceStats rxStats;
	DpdkDevice::DpdkDeviceStats txStats;
	device->getStatistics(rxStats);
	device->getStatistics(txStats);

	printf("\nStatistics for port %d:\n", device->getDeviceId());

	std::vector<std::string> columnNames;
	columnNames.push_back(" ");
	columnNames.push_back("Total Packets");
	columnNames.push_back("Packets/sec");
	columnNames.push_back("Total Bytes");
	columnNames.push_back("Bytes/sec");

	std::vector<int> columnLengths;
	columnLengths.push_back(10);
	columnLengths.push_back(15);
	columnLengths.push_back(15);
	columnLengths.push_back(15);
	columnLengths.push_back(15);

	TablePrinter printer(columnNames, columnLengths);

	std::stringstream totalRx;
	totalRx << "rx" << "|" << rxStats.aggregatedRxStats.packets << "|" << rxStats.aggregatedRxStats.packetsPerSec << "|" << rxStats.aggregatedRxStats.bytes << "|" << rxStats.aggregatedRxStats.bytesPerSec;
	printer.printRow(totalRx.str(), '|');

	std::stringstream totalTx;
	totalTx << "tx" << "|" << txStats.aggregatedTxStats.packets << "|" << txStats.aggregatedTxStats.packetsPerSec << "|" << txStats.aggregatedTxStats.bytes << "|" << txStats.aggregatedTxStats.bytesPerSec;
	printer.printRow(totalTx.str(), '|');
}

/**
 * main method of the application. Responsible for parsing user args, preparing worker thread configuration, creating the worker threads and activate them.
 * At program termination worker threads are stopped, statistics are collected from them and printed to console
 */
int main(int argc, char* argv[])
{
	AppName::init(argc, argv);

	std::vector<int> dpdkPortVec;

	CoreMask coreMaskToUse = getCoreMaskForAllMachineCores();

	int optionIndex = 0;
	char opt = 0;

	uint32_t mBufPoolSize = DEFAULT_MBUF_POOL_SIZE;
	uint16_t queueQuantity = DEFAULT_QUEUE_QUANTITY;

	while((opt = getopt_long (argc, argv, "d:c:m:q:hvl", DpdkBridgeOptions, &optionIndex)) != -1)
	{
		switch (opt)
		{
			case 0:
			{
				break;
			}
			case 'c':
			{
				coreMaskToUse = atoi(optarg);
				break;
			}
			case 'd':
			{
				string portListAsString = string(optarg);
				stringstream stream(portListAsString);
				string portAsString;
				int port;
				// break comma-separated string into string list
				while(getline(stream, portAsString, ','))
				{
					char c;
					std::stringstream stream2(portAsString);
					stream2 >> port;
					if (stream2.fail() || stream2.get(c))
					{
						// not an integer
						EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is invalid");
					}
					dpdkPortVec.push_back(port);
				}
				// verify list contains two ports
				if(dpdkPortVec.size()!=2)
				{
					EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK list must contain two values");
				}
				break;
			}
			case 'm':
			{
				mBufPoolSize = atoi(optarg);
				break;
			}
			case 'q':
			{
				queueQuantity = atoi(optarg);
				break;
			}
			case 'h':
			{
				printUsage();
				exit(0);
			}
			case 'l':
			{
				listDpdkPorts();
				exit(0);
			}
			case 'v':
			{
				printAppVersion();
				break;
			}
			default:
			{
				printUsage();
				exit(0);
			}
		}
	}

	// verify list is not empty
	if (dpdkPortVec.empty())
	{
		EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is empty. Please use the -d switch");
	}

	// extract core vector from core mask
	vector<SystemCore> coresToUse;
	createCoreVectorFromCoreMask(coreMaskToUse, coresToUse);

	// need minimum of 3 cores to start - 1 management core + 1 (or more) worker thread(s)
	if (coresToUse.size() < 3)
	{
		EXIT_WITH_ERROR("Needed minimum of 3 cores to start the application");
	}

	// initialize DPDK
	if (!DpdkDeviceList::initDpdk(coreMaskToUse, mBufPoolSize))
	{
		EXIT_WITH_ERROR("Couldn't initialize DPDK");
	}

	// removing DPDK master core from core mask because DPDK worker threads cannot run on master core
	coreMaskToUse = coreMaskToUse & ~(DpdkDeviceList::getInstance().getDpdkMasterCore().Mask);

	// re-calculate cores to use after removing master core
	coresToUse.clear();
	createCoreVectorFromCoreMask(coreMaskToUse, coresToUse);

	// collect the list of DPDK devices
	vector<DpdkDevice*> dpdkDevicesToUse;
	for (vector<int>::iterator iter = dpdkPortVec.begin(); iter != dpdkPortVec.end(); iter++)
	{
		DpdkDevice* dev = DpdkDeviceList::getInstance().getDeviceByPort(*iter);
		if (dev == NULL)
		{
			EXIT_WITH_ERROR("DPDK device for port %d doesn't exist", *iter);
		}
		dpdkDevicesToUse.push_back(dev);
	}

	// go over all devices and open them
	for (vector<DpdkDevice*>::iterator iter = dpdkDevicesToUse.begin(); iter != dpdkDevicesToUse.end(); iter++)
	{
		if (!(*iter)->openMultiQueues(queueQuantity, 1))
		{
			EXIT_WITH_ERROR("Couldn't open DPDK device #%d, PMD '%s'", (*iter)->getDeviceId(), (*iter)->getPMDName().c_str());
		}
	}

	// prepare configuration for every core
	AppWorkerConfig workerConfigArr[2];
	workerConfigArr[0].CoreId = coresToUse.at(0).Id;
	workerConfigArr[0].RxDevice = dpdkDevicesToUse.at(0);
	workerConfigArr[0].RxQueues = queueQuantity;
	workerConfigArr[0].TxDevice = dpdkDevicesToUse.at(1);
	workerConfigArr[1].CoreId = coresToUse.at(1).Id;
	workerConfigArr[1].RxDevice = dpdkDevicesToUse.at(1);
	workerConfigArr[1].RxQueues = queueQuantity;
	workerConfigArr[1].TxDevice = dpdkDevicesToUse.at(0);

	// create worker thread for every core
	vector<DpdkWorkerThread*> workerThreadVec;
	workerThreadVec.push_back(new AppWorkerThread(workerConfigArr[0]));
	workerThreadVec.push_back(new AppWorkerThread(workerConfigArr[1]));

	// start all worker threads
	if (!DpdkDeviceList::getInstance().startDpdkWorkerThreads(coreMaskToUse, workerThreadVec))
	{
		EXIT_WITH_ERROR("Couldn't start worker threads");
	}

	// register the on app close event to print summary stats on app termination
	DpdkBridgeArgs args;
	args.workerThreadsVector = &workerThreadVec;
	ApplicationEventHandler::getInstance().onApplicationInterrupted(onApplicationInterrupted, &args);

	// infinite loop (until program is terminated)
	uint64_t counter = 0;
    int statsCounter = 1;

    // Keep running while flag is on
    while (!args.shouldStop)
    {
		// Sleep for 1 second
		sleep(1);

		// Print stats every COLLECT_STATS_EVERY_SEC seconds
		if (counter % COLLECT_STATS_EVERY_SEC == 0)
		{
			// Clear screen and move to top left
			const char clr[] = { 27, '[', '2', 'J', '\0' };
        	const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' };
	        printf("%s%s", clr, topLeft);

			// Print devices traffic stats
			printf("Stats #%d\n==========\n", statsCounter++);
			printStats(dpdkDevicesToUse.at(0));
			printStats(dpdkDevicesToUse.at(1));
		}
		counter++;
    }
}
<commit_msg>Compilation fix in DpdkBridge<commit_after>/**
 * DPDK bridge example application
 * =======================================
 * This application demonstrates how to create a bridge between two network devices using PcapPlusPlus DPDK APIs.
 * It listens to two DPDK ports (a.k.a DPDK devices), and forwards all the traffic received on one port to the other, acting like a L2 bridge.
 *
 * The application is very similar to [DPDK's L2 forwarding example](https://doc.dpdk.org/guides/sample_app_ug/l2_forward_real_virtual.html)
 * and demonstrates how to achieve the same functionaly with PcapPlusPlus using less and easier to understand C++ code.
 *
 * The application uses the concept of worker threads. It creates 2 worker threads running in an endless loop (as long as the app is running):
 * one for receiving packets on NIC#1 and sending them to NIC#2, and another for receiving packets on NIC#2 and sending them to NIC#1.
 *
 * __Important__:
 * - This application runs only on Linux (DPDK is not supported on Windows and Mac OS X)
 * - This application (like all applications using DPDK) should be run as 'sudo'
 * - In order to test this application you need an envorinment where the bridge is connected directly (back-to-back) to the two machines the
 *   bridge wants to connect
*/

#include "Common.h"
#include "AppWorkerThread.h"

#include "DpdkDeviceList.h"
#include "IPv4Layer.h"
#include "TcpLayer.h"
#include "UdpLayer.h"
#include "SystemUtils.h"
#include "PcapPlusPlusVersion.h"
#include "TablePrinter.h"

#include <vector>
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <signal.h>
#include <getopt.h>
#include <string>
#include <sstream>
#include <unistd.h>

using namespace pcpp;

#define COLLECT_STATS_EVERY_SEC 1
#define DEFAULT_MBUF_POOL_SIZE 4095
#define DEFAULT_QUEUE_QUANTITY 1

static struct option DpdkBridgeOptions[] =
{
	{"dpdk-ports",  required_argument, 0, 'd'},
	{"core-mask",  optional_argument, 0, 'c'},
	{"mbuf-pool-size",  optional_argument, 0, 'm'},
	{"queue-quantity",  optional_argument, 0, 'q'},
	{"help", optional_argument, 0, 'h'},
	{"list", optional_argument, 0, 'l'},
	{"version", optional_argument, 0, 'v'},
	{0, 0, 0, 0}
};

/**
 * Print application usage
 */
void printUsage()
{
	printf("\nUsage:\n"
			"------\n"
			"%s [-hlv] [-c CORE_MASK] [-m POOL_SIZE] -d PORT_1,PORT_2 [-q QUEUE_QTY]\n"
			"\nOptions:\n\n"
			"    -h|--help                                  : Displays this help message and exits\n"
			"    -l|--list                                  : Print the list of DPDK ports and exits\n"
			"    -v|--version                               : Displays the current version and exits\n"
			"    -c|--core-mask CORE_MASK                   : Core mask of cores to use. For example: use 7 (binary 0111) to use cores 0,1,2.\n"
			"                                                 Default is using all cores except management core\n"
			"    -m|--mbuf-pool-size POOL_SIZE              : DPDK mBuf pool size to initialize DPDK with. Default value is 4095\n\n"
			"    -d|--dpdk-ports PORT_1,PORT_2              : A comma-separated list of two DPDK port numbers to be bridged.\n"
			"                                                 To see all available DPDK ports use the -l switch\n"
			"    -q|--queue-quantity QUEUE_QTY              : Quantity of RX queues to be opened for each DPDK device. Default value is 1\n", AppName::get().c_str());
}

/**
 * Print application version
 */
void printAppVersion()
{
	printf("%s %s\n", AppName::get().c_str(), getPcapPlusPlusVersionFull().c_str());
	printf("Built: %s\n", getBuildDateTime().c_str());
	printf("Built from: %s\n", getGitInfo().c_str());
	exit(0);
}

/**
 * Print to console all available DPDK ports. Used by the -l switch
 */
void listDpdkPorts()
{
	CoreMask coreMaskToUse = getCoreMaskForAllMachineCores();

	// initialize DPDK
	if (!DpdkDeviceList::initDpdk(coreMaskToUse, DEFAULT_MBUF_POOL_SIZE))
	{
		EXIT_WITH_ERROR("couldn't initialize DPDK");
	}

	printf("DPDK port list:\n");

	// go over all available DPDK devices and print info for each one
	vector<DpdkDevice*> deviceList = DpdkDeviceList::getInstance().getDpdkDeviceList();
	for (vector<DpdkDevice*>::iterator iter = deviceList.begin(); iter != deviceList.end(); iter++)
	{
		DpdkDevice* dev = *iter;
		printf("    Port #%d: MAC address='%s'; PCI address='%s'; PMD='%s'; Queues='%d/%d'\n",
				dev->getDeviceId(),
				dev->getMacAddress().toString().c_str(),
				dev->getPciAddress().toString().c_str(),
				dev->getPMDName().c_str(),
				dev->getTotalNumOfRxQueues(),
				dev->getTotalNumOfTxQueues()
		);
	}
}

struct DpdkBridgeArgs
{
	bool shouldStop;
	std::vector<DpdkWorkerThread*>* workerThreadsVector;

	DpdkBridgeArgs() : shouldStop(false), workerThreadsVector(NULL) {}
};

/**
 * The callback to be called when application is terminated by ctrl-c. Do cleanup and print summary stats
 */
void onApplicationInterrupted(void* cookie)
{
	DpdkBridgeArgs* args = (DpdkBridgeArgs*)cookie;

	printf("\n\nApplication stopped\n");

	// stop worker threads
	DpdkDeviceList::getInstance().stopDpdkWorkerThreads();

	args->shouldStop = true;
}

/**
 * Extract and print traffic stats from a device
 */
void printStats(DpdkDevice* device)
{
	DpdkDevice::DpdkDeviceStats rxStats;
	DpdkDevice::DpdkDeviceStats txStats;
	device->getStatistics(rxStats);
	device->getStatistics(txStats);

	printf("\nStatistics for port %d:\n", device->getDeviceId());

	std::vector<std::string> columnNames;
	columnNames.push_back(" ");
	columnNames.push_back("Total Packets");
	columnNames.push_back("Packets/sec");
	columnNames.push_back("Total Bytes");
	columnNames.push_back("Bytes/sec");

	std::vector<int> columnLengths;
	columnLengths.push_back(10);
	columnLengths.push_back(15);
	columnLengths.push_back(15);
	columnLengths.push_back(15);
	columnLengths.push_back(15);

	TablePrinter printer(columnNames, columnLengths);

	std::stringstream totalRx;
	totalRx << "rx" << "|" << rxStats.aggregatedRxStats.packets << "|" << rxStats.aggregatedRxStats.packetsPerSec << "|" << rxStats.aggregatedRxStats.bytes << "|" << rxStats.aggregatedRxStats.bytesPerSec;
	printer.printRow(totalRx.str(), '|');

	std::stringstream totalTx;
	totalTx << "tx" << "|" << txStats.aggregatedTxStats.packets << "|" << txStats.aggregatedTxStats.packetsPerSec << "|" << txStats.aggregatedTxStats.bytes << "|" << txStats.aggregatedTxStats.bytesPerSec;
	printer.printRow(totalTx.str(), '|');
}

/**
 * main method of the application. Responsible for parsing user args, preparing worker thread configuration, creating the worker threads and activate them.
 * At program termination worker threads are stopped, statistics are collected from them and printed to console
 */
int main(int argc, char* argv[])
{
	AppName::init(argc, argv);

	std::vector<int> dpdkPortVec;

	CoreMask coreMaskToUse = getCoreMaskForAllMachineCores();

	int optionIndex = 0;
	char opt = 0;

	uint32_t mBufPoolSize = DEFAULT_MBUF_POOL_SIZE;
	uint16_t queueQuantity = DEFAULT_QUEUE_QUANTITY;

	while((opt = getopt_long (argc, argv, "d:c:m:q:hvl", DpdkBridgeOptions, &optionIndex)) != -1)
	{
		switch (opt)
		{
			case 0:
			{
				break;
			}
			case 'c':
			{
				coreMaskToUse = atoi(optarg);
				break;
			}
			case 'd':
			{
				string portListAsString = string(optarg);
				stringstream stream(portListAsString);
				string portAsString;
				int port;
				// break comma-separated string into string list
				while(getline(stream, portAsString, ','))
				{
					char c;
					std::stringstream stream2(portAsString);
					stream2 >> port;
					if (stream2.fail() || stream2.get(c))
					{
						// not an integer
						EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is invalid");
					}
					dpdkPortVec.push_back(port);
				}
				// verify list contains two ports
				if(dpdkPortVec.size()!=2)
				{
					EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK list must contain two values");
				}
				break;
			}
			case 'm':
			{
				mBufPoolSize = atoi(optarg);
				break;
			}
			case 'q':
			{
				queueQuantity = atoi(optarg);
				break;
			}
			case 'h':
			{
				printUsage();
				exit(0);
			}
			case 'l':
			{
				listDpdkPorts();
				exit(0);
			}
			case 'v':
			{
				printAppVersion();
				break;
			}
			default:
			{
				printUsage();
				exit(0);
			}
		}
	}

	// verify list is not empty
	if (dpdkPortVec.empty())
	{
		EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is empty. Please use the -d switch");
	}

	// extract core vector from core mask
	vector<SystemCore> coresToUse;
	createCoreVectorFromCoreMask(coreMaskToUse, coresToUse);

	// need minimum of 3 cores to start - 1 management core + 1 (or more) worker thread(s)
	if (coresToUse.size() < 3)
	{
		EXIT_WITH_ERROR("Needed minimum of 3 cores to start the application");
	}

	// initialize DPDK
	if (!DpdkDeviceList::initDpdk(coreMaskToUse, mBufPoolSize))
	{
		EXIT_WITH_ERROR("Couldn't initialize DPDK");
	}

	// removing DPDK master core from core mask because DPDK worker threads cannot run on master core
	coreMaskToUse = coreMaskToUse & ~(DpdkDeviceList::getInstance().getDpdkMasterCore().Mask);

	// re-calculate cores to use after removing master core
	coresToUse.clear();
	createCoreVectorFromCoreMask(coreMaskToUse, coresToUse);

	// collect the list of DPDK devices
	vector<DpdkDevice*> dpdkDevicesToUse;
	for (vector<int>::iterator iter = dpdkPortVec.begin(); iter != dpdkPortVec.end(); iter++)
	{
		DpdkDevice* dev = DpdkDeviceList::getInstance().getDeviceByPort(*iter);
		if (dev == NULL)
		{
			EXIT_WITH_ERROR("DPDK device for port %d doesn't exist", *iter);
		}
		dpdkDevicesToUse.push_back(dev);
	}

	// go over all devices and open them
	for (vector<DpdkDevice*>::iterator iter = dpdkDevicesToUse.begin(); iter != dpdkDevicesToUse.end(); iter++)
	{
		if (!(*iter)->openMultiQueues(queueQuantity, 1))
		{
			EXIT_WITH_ERROR("Couldn't open DPDK device #%d, PMD '%s'", (*iter)->getDeviceId(), (*iter)->getPMDName().c_str());
		}
	}

	// prepare configuration for every core
	AppWorkerConfig workerConfigArr[2];
	workerConfigArr[0].CoreId = coresToUse.at(0).Id;
	workerConfigArr[0].RxDevice = dpdkDevicesToUse.at(0);
	workerConfigArr[0].RxQueues = queueQuantity;
	workerConfigArr[0].TxDevice = dpdkDevicesToUse.at(1);
	workerConfigArr[1].CoreId = coresToUse.at(1).Id;
	workerConfigArr[1].RxDevice = dpdkDevicesToUse.at(1);
	workerConfigArr[1].RxQueues = queueQuantity;
	workerConfigArr[1].TxDevice = dpdkDevicesToUse.at(0);

	// create worker thread for every core
	vector<DpdkWorkerThread*> workerThreadVec;
	workerThreadVec.push_back(new AppWorkerThread(workerConfigArr[0]));
	workerThreadVec.push_back(new AppWorkerThread(workerConfigArr[1]));

	// start all worker threads
	if (!DpdkDeviceList::getInstance().startDpdkWorkerThreads(coreMaskToUse, workerThreadVec))
	{
		EXIT_WITH_ERROR("Couldn't start worker threads");
	}

	// register the on app close event to print summary stats on app termination
	DpdkBridgeArgs args;
	args.workerThreadsVector = &workerThreadVec;
	ApplicationEventHandler::getInstance().onApplicationInterrupted(onApplicationInterrupted, &args);

	// infinite loop (until program is terminated)
	uint64_t counter = 0;
    int statsCounter = 1;

    // Keep running while flag is on
    while (!args.shouldStop)
    {
		// Sleep for 1 second
		sleep(1);

		// Print stats every COLLECT_STATS_EVERY_SEC seconds
		if (counter % COLLECT_STATS_EVERY_SEC == 0)
		{
			// Clear screen and move to top left
			const char clr[] = { 27, '[', '2', 'J', '\0' };
        	const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' };
	        printf("%s%s", clr, topLeft);

			// Print devices traffic stats
			printf("Stats #%d\n==========\n", statsCounter++);
			printStats(dpdkDevicesToUse.at(0));
			printStats(dpdkDevicesToUse.at(1));
		}
		counter++;
    }
}
<|endoftext|>


<commit_before>//____________________________________________________________________
//
// $Id: PatternDigits.C 28055 2008-08-18 00:33:20Z cholm $
//
// Draw hits in the specialised FMD event display
//
/** Display hits
    @ingroup FMD_script
 */
void
SpectraRaw(const char* file="raw.root", Int_t runno=0)
{
  gSystem->Load("libANALYSIS.so");
  gSystem->Load("libANALYSISalice.so");
  // gSystem->Load("libFMDanalysis.so");
  gSystem->Load("$(HOME)/scripts/foo.so");
  gSystem->Load("libFMDutil.so");

  AliCDBManager* cdb = AliCDBManager::Instance();
  const char* cdbUri = gSystem->Getenv("AMORE_CDB_URI");
  cdb->SetDefaultStorage(cdbUri);
  cdb->SetRun(runno);

  AliFMDParameters::Instance()->Init(kFALSE,
				     AliFMDParameters::kPulseGain|
				     AliFMDParameters::kPedestal|
				     AliFMDParameters::kDeadMap|
				     AliFMDParameters::kZeroSuppression|
				     AliFMDParameters::kAltroMap|
				     AliFMDParameters::kStripRange);
  AliFMDParameters::Instance()->SetSampleRate(2);

  AliFMDSpectraDisplay* d = new AliFMDSpectraDisplay;
  d->AddLoad(AliFMDInput::kRaw);
  d->SetRawFile(file);
  d->SetName("raw");
  d->SetTitle("Raw");
  d->Run();
}

//____________________________________________________________________
//
// EOF
//
<commit_msg>Stuff from aldaqdqm09<commit_after>//____________________________________________________________________
//
// $Id: PatternDigits.C 28055 2008-08-18 00:33:20Z cholm $
//
// Draw hits in the specialised FMD event display
//
/** Display hits
    @ingroup FMD_script
 */
Bool_t
CheckFile(const char* prefix, int number, TString& f)
{
  f = (Form("%s%d.csv", prefix, number));
  std::cout << "Checking if " << f << " exists ... " << std::flush;
  f = gSystem->Which("$(HOME)/calib/", f.Data());
  std::cout << '"' << f << '"' << std::endl;
  return !f.IsNull();
}
void
SpectraRaw(const char* file="raw.root", Int_t runno=0)
{
  gSystem->Load("libFMDutil.so");

  AliCDBManager* cdb = AliCDBManager::Instance();
  const char* cdbUri = gSystem->Getenv("AMORE_CDB_URI");
  cdb->SetDefaultStorage(cdbUri);
  cdb->SetRun(runno);

  AliFMDCalibStripRange* range = new AliFMDCalibStripRange;
  AliFMDCalibSampleRate* rate  = new AliFMDCalibSampleRate;
  AliFMDCalibPedestal*   peds  = new AliFMDCalibPedestal;
  AliFMDCalibGain*       gains = new AliFMDCalibGain;
  Bool_t gotConds = kFALSE;
  Bool_t gotPeds  = kFALSE;
  Bool_t gotGains = kFALSE;
  for (Int_t i = 1; i <= 3; i++) {
    TString f;
    if (CheckFile("conditions", i, f)) {
      gotConds = kTRUE;
      std::cout << "Reading conditions for FMD" <<i<< " from " <<f<< std::endl;
      std::ifstream in(f.Data());
      range->ReadFromFile(in);
      rate->ReadFromFile(in);
    }
    if (CheckFile("peds", i, f)) {
      gotPeds = kTRUE;
      std::cout << "Reading pedestals for FMD" <<i<< " from " <<f<< std::endl;
      std::ifstream in(f.Data());
      peds->ReadFromFile(in);
    }
    if (CheckFile("gains", i, f)) {
      gotGains = kTRUE;
      std::cout << "Reading gains for FMD" <<i<< " from " <<f<< std::endl;
      std::ifstream in(f.Data());
      gains->ReadFromFile(in);
    }
  }

  Int_t mask = (AliFMDParameters::kDeadMap|
		AliFMDParameters::kZeroSuppression|
		AliFMDParameters::kAltroMap);

  if (!gotConds) mask |= AliFMDParameters::kStripRange;
  if (!gotConds) mask |= AliFMDParameters::kSampleRate;
  if (!gotPeds)  mask |= AliFMDParameters::kPedestal;
  if (!gotGains) mask |= AliFMDParameters::kPulseGain;

  AliFMDParameters* pars = AliFMDParameters::Instance();
  pars->Init(kFALSE, mask);

  if (gotConds) pars->SetStripRange(range);
  if (gotConds) pars->SetSampleRate(rate);
  if (gotPeds)  pars->SetPedestal(peds);
  if (gotGains) pars->SetGain(gains);

  AliFMDSpectraDisplay* d = new AliFMDSpectraDisplay;
  d->AddLoad(AliFMDInput::kRaw);
  d->SetRawFile(file);
  d->SetName("raw");
  d->SetTitle("Raw");
  d->Run();
}

//____________________________________________________________________
//
// EOF
//
<|endoftext|>