//**************************************************************************************
//**************************************************************************************
//**************************************************************************************
//**************************************************************************************
void IntrinsicFeatureCalculator::GetObjectCentroids(vtkSmartPointer<vtkTable> table, int time)
{
	if(!intensityImage || !labelImage)
	{
		return;
	}

	//Compute features:
	typedef ftk::LabelImageToFeatures< IPixelT, LPixelT, 3 > FeatureCalcType;
	FeatureCalcType::Pointer labFilter = FeatureCalcType::New();
	if(useRegion)
	{
		labFilter->SetImageInputs( intensityImage->GetItkPtr<IPixelT>(time,intensityChannel), labelImage->GetItkPtr<LPixelT>(time,labelChannel), regionIndex, regionSize );
	}
	else
	{
		labFilter->SetImageInputs( intensityImage->GetItkPtr<IPixelT>(time,intensityChannel), labelImage->GetItkPtr<LPixelT>(time,labelChannel) );
	}
	labFilter->Update();

	//Init the table (headers):
	vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
	column->SetName( "centroid_x" );
	column->SetNumberOfValues(table->GetNumberOfRows());
	table->AddColumn(column);

	column = vtkSmartPointer<vtkDoubleArray>::New();
	column->SetName( "centroid_y" );
	column->SetNumberOfValues(table->GetNumberOfRows());
	table->AddColumn(column);

	column = vtkSmartPointer<vtkDoubleArray>::New();
	column->SetName( "centroid_z" );
	column->SetNumberOfValues(table->GetNumberOfRows());
	table->AddColumn(column);
	
	for (int i=0; i<(int)table->GetNumberOfRows(); ++i)
	{
		FeatureCalcType::LabelPixelType id = table->GetValue(i,0).ToInt();
		if(useIDs)
			if(IDs.find(id) == IDs.end()) continue;	//Don't care about this id, so skip it

		ftk::IntrinsicFeatures * features = labFilter->GetFeatures(id);
		table->SetValueByName( i, "centroid_x", vtkVariant((int)features->Centroid[0]) );
		table->SetValueByName( i, "centroid_y", vtkVariant((int)features->Centroid[1]) );
		if( labelImage->GetImageInfo()->numZSlices > 2 )
			table->SetValueByName( i, "centroid_z", vtkVariant((int)features->Centroid[2]) );
		else
			table->SetValueByName( i, "centroid_z", vtkVariant(0) );

		
	}
	return;
}
Ejemplo n.º 2
0
vtkSmartPointer<vtkTable> AppendLoadTable(std::string filename, vtkSmartPointer<vtkTable> initialTable , double tx, double ty, double tz)
{	//!Loads and apends a feature table into montage space
	/*!
	* Filename is for the loading the new file
	* initialTable is the table to append to
	* tx, ty, tz are the shift value to position into montage
	*/
	vtkSmartPointer<vtkTable> outputTable;
	vtkSmartPointer<vtkTable> newTable = ftk::LoadTable(filename);
	vtkVariant maxid = 0;
	if (initialTable->GetNumberOfRows() > 0)
	{
		for(vtkIdType r = 0; r < initialTable->GetNumberOfRows() ; r++ )
		{
			vtkVariant tempID = initialTable->GetValueByName( r, "ID");
			if (tempID > maxid)
			{
				maxid = tempID;
			}
		}//end for rows
	}
	for (vtkIdType rnew = 0; rnew < newTable->GetNumberOfRows() ; rnew++ )
	{
		vtkVariant tempID = newTable->GetValueByName(rnew , "ID");
		newTable->SetValueByName(rnew, "ID", vtkVariant(tempID.ToInt() + maxid.ToInt()));

		vtkVariant centroid_X = newTable->GetValueByName(rnew , "centroid_x");
		newTable->SetValueByName(rnew , "centroid_x",  vtkVariant(centroid_X.ToDouble() + tx));

		vtkVariant centroid_Y = newTable->GetValueByName(rnew , "centroid_y");
		newTable->SetValueByName(rnew , "centroid_y",  vtkVariant(centroid_Y.ToDouble() + ty));

		vtkVariant centroid_Z = newTable->GetValueByName(rnew , "centroid_z");
		newTable->SetValueByName(rnew , "centroid_z",  vtkVariant(centroid_Z.ToDouble() + tz));
	}
	if (initialTable->GetNumberOfRows() > 0)
	{
		outputTable = ftk::AppendTables(initialTable, newTable);
	}
	else
	{
		outputTable = newTable;
	}
	return outputTable;

}
//Compute features turned ON in doFeat and puts them in a new table
vtkSmartPointer<vtkTable> AssociativeFeatureCalculator::Compute(void)
{
	//Compute features:
	ftk::NuclearAssociationRules *assoc;
	if( inputs_set ){
		assoc = new ftk::NuclearAssociationRules("",0,lab_im, inp_im);
		assoc->AddAssociation( input_association->GetRuleName(), "", input_association->GetOutDistance(), input_association->GetInDistance(),	input_association->IsUseWholeObject(), input_association->IsUseBackgroundSubtraction(), input_association->IsUseMultiLevelThresholding(), input_association->GetNumberOfThresholds(), input_association->GetNumberIncludedInForeground(), input_association->GetAssocType(), input_association->get_path() );
	}
	else{
		assoc = new ftk::NuclearAssociationRules("",0);
		assoc->ReadRulesFromXML(inFilename);
	}
	assoc->PrintSelf();
	assoc->Compute();

	//Init the table (headers):
	vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
	vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
	column->SetName( "ID" );
	table->AddColumn(column);
	for (int i=0; i < assoc->GetNumofAssocRules(); ++i)
	{
		column = vtkSmartPointer<vtkDoubleArray>::New();
		column->SetName( (fPrefix+assoc->GetAssociationRules().at(i).GetRuleName()).c_str() );
		table->AddColumn(column);
	}

	//Now populate the table:
	std::vector<unsigned short> labels = assoc->GetLabels();
	float** vals = assoc->GetAssocFeaturesList();
	for (int i=0; i<(int)labels.size(); ++i)
	{
		unsigned short id = labels.at(i);
		if(id == 0) continue;

		vtkSmartPointer<vtkVariantArray> row = vtkSmartPointer<vtkVariantArray>::New();
		row->InsertNextValue( vtkVariant(id) );
		for (int r=0; r<assoc->GetNumofAssocRules(); ++r)
		{
			row->InsertNextValue( vtkVariant(vals[r][i]) );
		}
		table->InsertNextRow(row);
	}
	delete assoc;
	return table;
}
Ejemplo n.º 4
0
vtkSmartPointer<vtkTable> LoadXYZTable(std::string filename)
{
	/*!
	*	Read a tab deliminated text file of xyz coords and create a vtkTable
	*/
	if( !FileExists(filename.c_str()) )
		return NULL;

	const int MAXLINESIZE = 10024;	
	char line[MAXLINESIZE];

	//Open the file:
	ifstream inFile; 
	inFile.open( filename.c_str() );
	if ( !inFile.is_open() )
		return NULL;

	vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();	

	//!Create THE HEADER INFO:
	/**Creates the vtk table header information to reference the columns by*/

	vtkSmartPointer<vtkDoubleArray> Xcolumn = vtkSmartPointer<vtkDoubleArray>::New();
	Xcolumn->SetName( "centroid_x");
	table->AddColumn(Xcolumn);

	vtkSmartPointer<vtkDoubleArray> Ycolumn = vtkSmartPointer<vtkDoubleArray>::New();
	Ycolumn->SetName( "centroid_y");
	table->AddColumn(Ycolumn);

	vtkSmartPointer<vtkDoubleArray> Zcolumn = vtkSmartPointer<vtkDoubleArray>::New();
	Zcolumn->SetName( "centroid_z");
	table->AddColumn(Zcolumn);
	//!LOAD THE DATA:
	/*!
	* Reads all the data into table
	* Note: reads in as float but stores as vtkVariant
	*/
	inFile.getline(line, MAXLINESIZE);
	while ( !inFile.eof() ) //Get all values
	{
		vtkSmartPointer<vtkVariantArray> row = vtkSmartPointer<vtkVariantArray>::New();
		char * pch = strtok (line," \t");
		while (pch != NULL)
		{
			row->InsertNextValue( vtkVariant( atof(pch) ) );
			pch = strtok (NULL, " \t");
		}
		table->InsertNextRow(row);
		inFile.getline(line, MAXLINESIZE);
	}
	inFile.close();
	
	return table;
}
Ejemplo n.º 5
0
bool SelectiveClustering::AddCluster(vtkIdType key, std::set<vtkIdType> ClusterSelectionSet)
{
	/*! 
	* Adds a unique new cluster
	* replaces cluster if one with the key currently exists
	*/
	this->iter = this->ClusterMap.find(key);
	if ((this->ClusterMap.size() > 0) && (this->iter != this->ClusterMap.end()))
	{
		//Remove old item
		this->ClusterMap.erase(iter);
	}
	this->ClusterMap[key] = ClusterSelectionSet;
	this->AddRowToClusterTable(key, vtkVariant(ClusterSelectionSet.size()), NULL);
	emit ClusterChanged();
	return true;
}
Ejemplo n.º 6
0
vtkIdType SelectiveClustering::AddCluster(std::set<vtkIdType> ClusterSelectionSet)
{
	/*! 
	* Create a new cluster from a selection
	*/
	vtkIdType newKey = this->ClusterMap.size();
	this->iter = this->ClusterMap.find(newKey);
	while ((this->ClusterMap.size() > 0) &&(this->iter != this->ClusterMap.end()))
	{
		newKey++;
		this->iter = this->ClusterMap.find(newKey);
	}
	this->ClusterMap[newKey] = ClusterSelectionSet;
	this->AddRowToClusterTable(newKey, vtkVariant(ClusterSelectionSet.size()), NULL);

	emit ClusterChanged();
	return newKey;
}
Ejemplo n.º 7
0
//-+#+-+#+-+#+-+#+-+#+-+#+-+#+-+#+-+#+-+#+-+#+-+#+-+#+-+#+-+#+-+#+-+#+-+#+-
int ovOrlandoReader::ProcessRequest(
  vtkInformation *request,
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
{
  vtkInformation *outInfo = outputVector->GetInformationObject( 0 );

  if( request->Has( vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT() ) )
  {
    return this->RequestDataObject( request, inputVector, outputVector );
  }

  if( request->Has( vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT() ) )
  {
    return 1;
  }

  if( request->Has( vtkDemandDrivenPipeline::REQUEST_INFORMATION() ) )
  {
    return 1;
  }

  if( request->Has( vtkDemandDrivenPipeline::REQUEST_DATA() ) &&
      0 == outInfo->Get( vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER() ) )
  {
    vtkDebugMacro( << "Reading orlando data ...");

    ovOrlandoTagInfo *tagInfo = ovOrlandoTagInfo::GetInfo();
    
    // create and set up a graph with pedigree and tag arrays
    // (the pedigree array is used to track vertices by name)
    vtkSmartPointer< vtkMutableDirectedGraph > graph =
      vtkSmartPointer< vtkMutableDirectedGraph >::New();
    vtkSmartPointer< vtkStringArray > pedigreeArray = vtkSmartPointer< vtkStringArray >::New();
    pedigreeArray->SetName( "pedigree" );
    graph->GetVertexData()->AddArray( pedigreeArray );
    graph->GetVertexData()->SetPedigreeIds( pedigreeArray );

    // the color array is used for edge coloring, this will be manipulated internally by the
    // restrict graph algorithm
    vtkSmartPointer< vtkIntArray > vertexColorArray = vtkSmartPointer< vtkIntArray >::New();
    vertexColorArray->SetName( "color" );
    graph->GetVertexData()->AddArray( vertexColorArray );

    // the size array is used to determine the size of each vertex
    vtkSmartPointer< vtkDoubleArray > sizeArray = vtkSmartPointer< vtkDoubleArray >::New();
    sizeArray->SetName( "size" );
    graph->GetVertexData()->AddArray( sizeArray );
    graph->GetVertexData()->SetActiveScalars( sizeArray->GetName() );

    // the label array is used to track each entries full un-marked-up label
    vtkSmartPointer< vtkStringArray > labelArray = vtkSmartPointer< vtkStringArray >::New();
    labelArray->SetName( "label" );
    graph->GetVertexData()->AddArray( labelArray );

    // the content array is used to track each entries full un-marked-up content
    vtkSmartPointer< vtkStringArray > authorContentArray = vtkSmartPointer< vtkStringArray >::New();
    authorContentArray->SetName( "content" );
    graph->GetVertexData()->AddArray( authorContentArray );

    // the stemmed content array is used to track each entries full un-marked-up, stemmed content
    vtkSmartPointer< vtkStringArray > authorStemmedContentArray =
      vtkSmartPointer< vtkStringArray >::New();
    authorStemmedContentArray->SetName( "stemmedContent" );
    graph->GetVertexData()->AddArray( authorStemmedContentArray );

    // the birth and death arrays track author birth and death dates
    vtkSmartPointer< vtkIntArray > birthArray = vtkSmartPointer< vtkIntArray >::New();
    birthArray->SetName( "birth" );
    graph->GetVertexData()->AddArray( birthArray );
    vtkSmartPointer< vtkIntArray > deathArray = vtkSmartPointer< vtkIntArray >::New();
    deathArray->SetName( "death" );
    graph->GetVertexData()->AddArray( deathArray );

    // the gender and writer type of the author
    vtkSmartPointer< vtkIntArray > genderArray = vtkSmartPointer< vtkIntArray >::New();
    genderArray->SetName( "gender" );
    graph->GetVertexData()->AddArray( genderArray );
    vtkSmartPointer< vtkIntArray > writerTypeArray = vtkSmartPointer< vtkIntArray >::New();
    writerTypeArray->SetName( "writerType" );
    graph->GetVertexData()->AddArray( writerTypeArray );

    // the tag array is used to keep a list of tags which associates the two vertices
    vtkSmartPointer< vtkStringArray > tagArray = vtkSmartPointer< vtkStringArray >::New();
    tagArray->SetName( "tags" );
    graph->GetEdgeData()->AddArray( tagArray );

    // the color array is used for edge coloring, this will be manipulated internally by the
    // restrict graph algorithm
    vtkSmartPointer< vtkVariantArray > edgeColorArray = vtkSmartPointer< vtkVariantArray >::New();
    edgeColorArray->SetName( "color" );
    graph->GetEdgeData()->AddArray( edgeColorArray );
    
    // the content array is used to keep a string of raw text associated with every edge
    vtkSmartPointer< vtkStringArray > contentArray = vtkSmartPointer< vtkStringArray >::New();
    contentArray->SetName( "content" );
    graph->GetEdgeData()->AddArray( contentArray );

    // the stemmed content array is used to keep a string of raw stemmed text associated with
    // every edge
    vtkSmartPointer< vtkStringArray > stemmedContentArray = vtkSmartPointer< vtkStringArray >::New();
    stemmedContentArray->SetName( "stemmedContent" );
    graph->GetEdgeData()->AddArray( stemmedContentArray );

    // A string to store the current active tags and mark them all as '0' chars to begin with.
    // Every time we open a tag in the association types vector we will set the tag to '1',
    // and every time the tag closes we will set it back to '0'.  This string will then be
    // copied every time we add a new edge.
    ovString currentTagArray( tagInfo->GetNumberOfTags(), '0' );
    
    // Keep track of the content so that it can be added to the author node
    ovString authorContent;

    try
    {
      vtkIdType currentVertexId = -1, currentConnectingVertexId = -1;
      vtkStdString currentVertexPedigree = "";
      bool inBirthTag = false, inDeathTag = false, inOrlandoHeaderTag = false;
      this->CreateReader();
      
      // count how many entries are in the file (for progress reporting)
      double totalEntries = 0;
      ovString line;
      vtkstd::ifstream fileStream( this->FileName.c_str() );
      if( !fileStream.is_open() ) throw vtkstd::runtime_error( "Unable to stream file." );
      // this count may be inaccurate since it doesn't account for spacing (ie: "< ENTRY"),
      // however, it is nice and fast and if the count is incorrect then the only side effect
      // is incorrect progress reporting which really isn't so bad (so worth the uncertainty)
      while( getline( fileStream, line ) ) if( line.find( "<ENTRY" ) ) totalEntries++;
      fileStream.close();
      
      // process each node, one at a time
      double numEntries = 0, progress;

      bool inDiv0 = false, inDiv1 = false, inDiv2 = false, inP = false, inP2 = false;
      bool startQuote = false, endQuote = false;
      bool inDate = false, inBibcit = false, inHeading = false, inScholarnote = false;
      ovString div0Content, div1Content, div2Content, pContent, p2Content;
      ovIntVector div0Vertices, div1Vertices, div2Vertices, pVertices, p2Vertices;

      while( this->ParseNode() )
      {
        // ignore node type 14 (#text stuff that we don't need)
        if( 14 == this->CurrentNode.NodeType ) continue;
        
        // make sure to skip anything inside the orlando header tag
        if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "ORLANDOHEADER" ) )
        {
          if( !( this->CurrentNode.IsEmptyElement ) && this->CurrentNode.IsOpeningElement() )
          {
            inOrlandoHeaderTag = true;
          }
          else if( this->CurrentNode.IsClosingElement() )
          {
            inOrlandoHeaderTag = false;
          }
          continue;
        }

        if( inOrlandoHeaderTag ) continue;

        // This node is an entry (vertex)
        if( 1 == this->CurrentNode.Depth &&
            0 == xmlStrcmp( BAD_CAST "ENTRY", this->CurrentNode.Name ) )
        {
          if( this->CurrentNode.IsOpeningElement() )
          {
            progress = numEntries / totalEntries;
            this->InvokeEvent( vtkCommand::ProgressEvent, &( progress ) );
            
            // get the pedigree (author's name) from this node's id attribute
            const char *pedigree =
              ( char* )( xmlTextReaderGetAttribute( this->Reader, BAD_CAST "standard" ) );

            // create a new vertex using the Id (author name) as the pedigree
            vtkSmartPointer< vtkVariantArray > array = vtkSmartPointer< vtkVariantArray >::New();
            array->SetNumberOfComponents( 10 );
            array->SetNumberOfTuples( 1 );
            array->SetValue( 0, vtkVariant( pedigree ) ); // pedigree
            array->SetValue( 1, 1 ); // color
            array->SetValue( 2, 2 ); // size
            array->SetValue( 3, vtkVariant( "" ) ); // label
            array->SetValue( 4, vtkVariant( "" ) ); // content
            array->SetValue( 5, vtkVariant( "" ) ); // stemmed content
            array->SetValue( 6, 0 ); // birth date
            array->SetValue( 7, 0 ); // death date
            array->SetValue( 8, ovOrlandoReader::GenderTypeUnknown ); // gender
            array->SetValue( 9, ovOrlandoReader::WriterTypeNone ); // writer type
            currentVertexId = graph->AddVertex( array );
            currentVertexPedigree = pedigreeArray->GetValue( currentVertexId );
          }
          
          if( this->CurrentNode.IsEmptyElement ||
              this->CurrentNode.IsClosingElement() )
          { // no more child vertices for this vertex

            // add the matching content
            authorContentArray->SetValue( currentVertexId, authorContent );
            authorStemmedContentArray->SetValue( currentVertexId, stemWords( authorContent ) );
            authorContent = "";
            currentVertexId = -1;
            numEntries++;
          }
        }
        else if( 0 <= currentVertexId )
        {
          // we're in an open NAME tag which is closing
          if( 0 <= currentConnectingVertexId &&
              this->CurrentNode.IsClosingElement() &&
              0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "NAME" ) )
          {
            currentConnectingVertexId = -1;
          }
          else
          {
            if( this->CurrentNode.HasContent )
            {
              // get and clean the content
              ovString content = ( char* )( this->CurrentNode.Content );
              size_t start = content.find_first_not_of("\t\n\r");
              if( start != vtkstd::string::npos )
                content = content.substr( start, content.find_last_not_of("\t\n\r") - start + 1 );
              
              if( 0 < content.length() )
              {
                // format text from certain tags
                if( inDate ) content = content + " ";
                else if( inBibcit ) content = " (" + content + ") ";
                else if( inHeading ) content = content + ". ";
                else if( startQuote )
                {
                  content = " \"" + content;
                  startQuote = false;
                }
                else if( endQuote )
                {
                  content = "\" " + content;
                  endQuote = false;
                }
                else if( inScholarnote ) content = " " + content + " ";

                // add to author content
                authorContent.append( content );
                
                // add to currently open div tags
                if( inP2 ) p2Content.append( content );
                if( inP ) pContent.append( content );
                if( inDiv2 ) div2Content.append( content );
                if( inDiv1 ) div1Content.append( content );
                if( inDiv0 ) div0Content.append( content );
              }
            }
            
            // Concerning the state of DIV0, DIV1, DIV2 and P tags when a NAME tag is found:
            // All NAME tags are inside of DIV1, DIV2 or P tags
            // A DIV2 tag is always inside of a DIV1 tag, and P tags are always inside a DIV0,
            // DIV1, DIV2 or another P tag.
            // We use the variables inDiv1, inDiv2 and inP to track which tag and level we are
            // currently in, so that when we close that tag then any names which were found
            // inside can have the text added as their content.
            if( !this->CurrentNode.IsEmptyElement )
            {
              if( this->CurrentNode.IsOpeningElement() )
              {
                if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "P" ) )
                {
                  if( inP ) inP2 = true;
                  else inP = true;
                }
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DIV2" ) )
                  inDiv2 = true;
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DIV1" ) )
                  inDiv1 = true;
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DIV0" ) )
                  inDiv0 = true;
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DATE" ) )
                  inDate = true;
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "BIBCIT" ) )
                  inBibcit = true;
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "HEADING" ) )
                  inHeading = true;
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "QUOTE" ) )
                  startQuote = true;
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "SCHOLARNOTE" ) )
                  inScholarnote = true;
              }
              else if( this->CurrentNode.IsClosingElement() )
              {
                if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "P" ) )
                {
                  if( inP2 )
                  {
                    // set the content array for any NAMES which were opened inside this tag
                    while( !p2Vertices.empty() )
                    {
                      contentArray->SetValue( p2Vertices.back(), p2Content );
                      stemmedContentArray->SetValue( p2Vertices.back(), stemWords( p2Content ) );
                      p2Vertices.pop_back();
                    }

                    inP2 = false;
                    p2Content = "";
                  }
                  else
                  {
                    // set the content array for any NAMES which were opened inside this tag
                    while( !pVertices.empty() )
                    {
                      contentArray->SetValue( pVertices.back(), pContent );
                      stemmedContentArray->SetValue( pVertices.back(), stemWords( pContent ) );
                      pVertices.pop_back();
                    }

                    inP = false;
                    pContent = "";
                  }
                }
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DIV2" ) )
                {
                  // set the content array for any NAMES which were opened inside this tag
                  while( !div2Vertices.empty() )
                  {
                    contentArray->SetValue( div2Vertices.back(), div2Content );
                    stemmedContentArray->SetValue( div2Vertices.back(), stemWords( div2Content ) );
                    div2Vertices.pop_back();
                  }

                  inDiv2 = false;
                  div2Content = "";
                }
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DIV1" ) )
                {
                  // set the content array for any NAMES which were opened inside this tag
                  while( !div1Vertices.empty() )
                  {
                    contentArray->SetValue( div1Vertices.back(), div1Content );
                    stemmedContentArray->SetValue( div1Vertices.back(), stemWords( div1Content ) );
                    div1Vertices.pop_back();
                  }

                  inDiv1 = false;
                  div1Content = "";
                }
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DIV0" ) )
                {
                  // set the content array for any NAMES which were opened inside this tag
                  while( !div0Vertices.empty() )
                  {
                    contentArray->SetValue( div0Vertices.back(), div0Content );
                    stemmedContentArray->SetValue( div0Vertices.back(), stemWords( div0Content ) );
                    div0Vertices.pop_back();
                  }

                  inDiv0 = false;
                  div0Content = "";
                }
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DATE" ) )
                  inDate = false;
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "BIBCIT" ) )
                  inBibcit = false;
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "HEADING" ) )
                  inHeading = false;
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "QUOTE" ) )
                  endQuote = true;
                else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "SCHOLARNOTE" ) )
                  inScholarnote = false;
              }
            }

            // get the pedigree (associate's name) from this node's standard attribute
            const char *pedigree =
              ( char* )( xmlTextReaderGetAttribute( this->Reader, BAD_CAST "STANDARD" ) );

            // This node describes an association (edge)
            if( this->CurrentNode.IsOpeningElement() &&
                0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "NAME" ) &&
                currentVertexPedigree != vtkStdString( pedigree ) )
            {
              // Create a new vertex (if necessary) using the standard (association's name) as the
              // pedigree
              if( -1 == graph->FindVertex( pedigree ) )
              {
                vtkSmartPointer< vtkVariantArray > array = vtkSmartPointer< vtkVariantArray >::New();
                array->SetNumberOfComponents( 10 );
                array->SetNumberOfTuples( 1 );
                array->SetValue( 0, vtkVariant( pedigree ) ); // pedigree
                array->SetValue( 1, 0 ); // color
                array->SetValue( 2, 1 ); // size
                array->SetValue( 3, vtkVariant( "" ) ); // label
                array->SetValue( 4, vtkVariant( "" ) ); // content (blank for now)
                array->SetValue( 5, vtkVariant( "" ) ); // stemmed content (blank for now)
                array->SetValue( 6, 0 ); // birth date
                array->SetValue( 7, 0 ); // death date
                array->SetValue( 8, ovOrlandoReader::GenderTypeUnknown ); // gender
                array->SetValue( 9, ovOrlandoReader::WriterTypeNone ); // writer type
                graph->AddVertex( array );
              }
              
              // Create an edge from the current vertex to the new vertex
              vtkSmartPointer< vtkVariantArray > array = vtkSmartPointer< vtkVariantArray >::New();
              array->SetNumberOfComponents( 4 );
              array->SetNumberOfTuples( 1 );
              array->SetValue( 0, vtkVariant( currentTagArray ) ); // tags
              array->SetValue( 1, 0 ); // color (set by the restrict filter)
              array->SetValue( 2, vtkVariant( "" ) ); // content (blank for now)
              array->SetValue( 3, vtkVariant( "" ) ); // stemmed content (blank for now)
              vtkEdgeType e = graph->AddEdge( currentVertexPedigree, pedigree, array );

              // and track which content paragraph tag type we are currently in for content
              if( inP2 ) p2Vertices.push_back( e.Id );
              else if( inP ) pVertices.push_back( e.Id );
              else if( inDiv2 ) div2Vertices.push_back( e.Id );
              else if( inDiv1 ) div1Vertices.push_back( e.Id );
              else if( inDiv0 ) div0Vertices.push_back( e.Id );

              // determine the connecting vertex' id if this isn't an empty element
              if( !( this->CurrentNode.IsEmptyElement ) )
              {
                currentConnectingVertexId = pedigreeArray->LookupValue( pedigree );
              }
            }
            // This node may describe an association type (edge tag) or birth/death dates
            else
            {
              // if this is a biography tag then record the author's gender and writer type
              if( this->CurrentNode.IsOpeningElement() &&
                  0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "BIOGRAPHY" ) )
              {
                // get the current author's gender and writer type from the the biography tag
                genderArray->SetValue( currentVertexId,
                  ovOrlandoReader::GenderTypeFromString(
                    ( char* )( xmlTextReaderGetAttribute( this->Reader, BAD_CAST "SEX" ) ) ) );
                writerTypeArray->SetValue( currentVertexId,
                  ovOrlandoReader::WriterTypeFromString(
                    ( char* )( xmlTextReaderGetAttribute( this->Reader, BAD_CAST "PERSON" ) ) ) );
              }

              // first let's see if the name is in our tag list
              int index = -1;
              if( !( this->CurrentNode.IsEmptyElement ) && this->CurrentNode.IsOpeningElement() )
              {
                index = tagInfo->FindTagIndexFromName( ( char* )( this->CurrentNode.Name ) );
                if( 0 <= index ) // we found a match
                {
                  // are we already in a connecting vertex (NAME) tag?
                  if( 0 <= currentConnectingVertexId )
                  {
                    tagArray->GetValue( currentConnectingVertexId ).at( index ) = '1';
                  }

                  // opening element, mark the tag as true
                  currentTagArray[index] = '1';
                }
              }
              else if( this->CurrentNode.IsClosingElement() )
              {
                index = tagInfo->FindTagIndexFromName( ( char* )( this->CurrentNode.Name ) );
                if( 0 <= index ) // we found a match
                { // closing element, mark the tag as false
                  currentTagArray[index] = '0';
                }
              }
              
              // Now handle birth and death tags, and any dates associated with them
              // Is this a date inside a birth tag?
              if( inBirthTag && 
                  this->CurrentNode.IsOpeningElement() &&
                  ( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DATE" ) ||
                    0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DATESTRUCT" ) ||
                    0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DATERANGE" ) ) )
              {
                ovDate newDate( ( char* )(
                  xmlTextReaderGetAttribute( this->Reader, 
                  0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DATERANGE" ) ?
                  BAD_CAST "FROM" : BAD_CAST "VALUE" ) ) );
                ovDate curDate( ( birthArray->GetValue( currentVertexId ) ) );
                
                // make sure the date is valid
                if( newDate.IsSet() )
                {
                  // if we don't currently have a date, use the new one
                  if( !curDate.IsSet() )
                  {
                    birthArray->SetValue( currentVertexId, newDate.ToInt() );
                  }
                  // We already have a date, so make sure the new date is earlier and has as much
                  // information
                  else if( ( curDate > newDate ) &&
                           ( 0 == curDate.day || 0 < newDate.day ) &&
                           ( 0 == curDate.month || 0 < newDate.month ) )
                  {
                    birthArray->SetValue( currentVertexId, newDate.ToInt() );
                  }
                }
              }
              // ...or maybe a date inside a death tag?
              else if( inDeathTag &&
                       this->CurrentNode.IsOpeningElement() &&
                       ( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DATE" ) ||
                         0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DATESTRUCT" ) ||
                         0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DATERANGE" ) ) )
              {
                ovDate newDate( ( char* )(
                  xmlTextReaderGetAttribute( this->Reader, 
                  0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DATERANGE" ) ?
                  BAD_CAST "TO" : BAD_CAST "VALUE" ) ) );
                ovDate curDate( deathArray->GetValue( currentVertexId ) );
  
                // make sure the date is valid
                if( newDate.IsSet() )
                {
                  // if we don't currently have a date, use the new one
                  if( !curDate.IsSet() )
                  {
                    deathArray->SetValue( currentVertexId, newDate.ToInt() );
                  }
                  // We already have a date, so make sure the new date is later and has as much
                  // information
                  else if( ( curDate < newDate ) &&
                           ( 0 == curDate.day || 0 < newDate.day ) &&
                           ( 0 == curDate.month || 0 < newDate.month ) )
                  {
                    deathArray->SetValue( currentVertexId, newDate.ToInt() );
                  }
                }
              }
              // ...or maybe a birth tag?
              else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "BIRTH" ) )
              {
                if( !( this->CurrentNode.IsEmptyElement ) && this->CurrentNode.IsOpeningElement() )
                {
                  inBirthTag = true;
                }
                else if( this->CurrentNode.IsClosingElement() )
                {
                  inBirthTag = false;
                }
              }
              // ...or maybe a death tag?
              else if( 0 == xmlStrcmp( this->CurrentNode.Name, BAD_CAST "DEATH" ) )
              {
                if( !( this->CurrentNode.IsEmptyElement ) && this->CurrentNode.IsOpeningElement() )
                {
                  inDeathTag = true;
                }
                else if( this->CurrentNode.IsClosingElement() )
                {
                  inDeathTag = false;
                }
              }
            }
          }
        }
      } // end while

      this->FreeReader();
    }
    catch( vtkstd::exception &e )
    {
      vtkErrorMacro( << e.what() );
      return 0;
    }
   
    vtkDebugMacro(<< "Read " 
      << graph->GetNumberOfVertices() 
      << " vertices and "
      << graph->GetNumberOfEdges() 
      << " edges.\n");
  
    // Copy graph into output.
    vtkGraph* const output =
      vtkGraph::SafeDownCast( outInfo->Get( vtkDataObject::DATA_OBJECT() ) );
    if( !output->CheckedShallowCopy( graph ) )
    {
      vtkErrorMacro( << "Invalid graph structure, returning empty graph." );
      return 0;
    }
Ejemplo n.º 8
0
// --------------------------------------------------------------------------
void voIOManager::fillExtendedTable(vtkTable* sourceTable, vtkExtendedTable* destTable,
                                    const voDelimitedTextImportSettings& settings)
{
  // vtkExtendedTable settings
  bool transpose = settings.value(voDelimitedTextImportSettings::Transpose).toBool();
  if (transpose)
    {
    voUtils::transposeTable(sourceTable);
    }

  int numberOfRowMetaDataTypes =
      settings.value(voDelimitedTextImportSettings::NumberOfRowMetaDataTypes).toInt();
  int numberOfColumnMetaDataTypes =
      settings.value(voDelimitedTextImportSettings::NumberOfColumnMetaDataTypes).toInt();

  Q_ASSERT(numberOfColumnMetaDataTypes <= sourceTable->GetNumberOfRows());

  //sourceTable->Dump();

  // ColumnMetaData
  vtkNew<vtkTable> columnMetaData;
  for (int cid = numberOfRowMetaDataTypes; cid < sourceTable->GetNumberOfColumns(); ++cid)
    {
    vtkStringArray * column = vtkStringArray::SafeDownCast(sourceTable->GetColumn(cid));
    Q_ASSERT(column);
    for (int rid = 0; rid < numberOfColumnMetaDataTypes; ++rid)
      {
      vtkSmartPointer<vtkStringArray> newColumn;
      if (cid == numberOfRowMetaDataTypes)
        {
        newColumn = vtkSmartPointer<vtkStringArray>::New();
        newColumn->SetNumberOfValues(sourceTable->GetNumberOfColumns() - numberOfRowMetaDataTypes);
        columnMetaData->AddColumn(newColumn);
        }
      else
        {
        newColumn = vtkStringArray::SafeDownCast(columnMetaData->GetColumn(rid));
        }
      Q_ASSERT(newColumn);
      vtkStdString value = column->GetValue(rid);
      newColumn->SetValue(cid - numberOfRowMetaDataTypes, value);
      }
    }

  //columnMetaData->Dump();

  // ColumnMetaDataLabels
  vtkNew<vtkStringArray> columnMetaDataLabels;
  if (numberOfRowMetaDataTypes > 0) // If there are no row metadata types, there is no room for column metadata labels
    {
    for (int rid = 0; rid < numberOfColumnMetaDataTypes; rid++)
      {
      columnMetaDataLabels->InsertNextValue(sourceTable->GetValue(rid, 0).ToString());
      }
    }

  // RowMetaData
  vtkNew<vtkTable> rowMetaData;
  Q_ASSERT(numberOfRowMetaDataTypes <= sourceTable->GetNumberOfColumns());
  for (int cid = 0; cid < numberOfRowMetaDataTypes; ++cid)
    {
    vtkStringArray * column = vtkStringArray::SafeDownCast(sourceTable->GetColumn(cid));
    Q_ASSERT(column);
    for (int rid = numberOfColumnMetaDataTypes; rid < column->GetNumberOfValues(); ++rid)
      {
      vtkSmartPointer<vtkStringArray> newColumn;
      if (rid == numberOfColumnMetaDataTypes)
        {
        newColumn = vtkSmartPointer<vtkStringArray>::New();
        newColumn->SetNumberOfValues(sourceTable->GetNumberOfRows() - numberOfColumnMetaDataTypes);
        rowMetaData->AddColumn(newColumn);
        }
      else
        {
        newColumn = vtkStringArray::SafeDownCast(rowMetaData->GetColumn(cid));
        }
      Q_ASSERT(newColumn);
      vtkStdString value = column->GetValue(rid);
      newColumn->SetValue(rid - numberOfColumnMetaDataTypes, value);
      }
    }

  //rowMetaData->Dump();

  // RowMetaDataLabels
  vtkNew<vtkStringArray> rowMetaDataLabels;
  if (numberOfColumnMetaDataTypes > 0) // If there are no column metadata types, there is no room for row metadata labels
    {
    for (int cid = 0; cid < numberOfRowMetaDataTypes; cid++)
      {
      rowMetaDataLabels->InsertNextValue(sourceTable->GetValue(0, cid).ToString());
      }
    }

  // Data
  vtkNew<vtkTable> data;
  for (int cid = numberOfRowMetaDataTypes; cid < sourceTable->GetNumberOfColumns(); ++cid)
    {
    vtkStringArray * column = vtkStringArray::SafeDownCast(sourceTable->GetColumn(cid));
    Q_ASSERT(column);

    // determine whether this column contains numerical or categorical data.
    vtkNew<vtkDoubleArray> doubleColumn;
    vtkNew<vtkStringArray> stringColumn;
    vtkStdString value = column->GetValue(numberOfColumnMetaDataTypes);
    bool dataIsNumerical = false;
    vtkVariant(value).ToDouble(&dataIsNumerical);
    if (dataIsNumerical)
      {
      doubleColumn->SetNumberOfValues(
        sourceTable->GetNumberOfRows() - numberOfColumnMetaDataTypes);
      data->AddColumn(doubleColumn.GetPointer());
      }
    else
      {
      stringColumn->SetNumberOfValues(
        sourceTable->GetNumberOfRows() - numberOfColumnMetaDataTypes);
      data->AddColumn(stringColumn.GetPointer());
      }

    for (int rid = numberOfColumnMetaDataTypes; rid < column->GetNumberOfValues(); ++rid)
      {
      vtkStdString value = column->GetValue(rid);
      if (dataIsNumerical)
        {
        // Convert to numeric
        bool ok = false;
        double doubleValue = vtkVariant(value).ToDouble(&ok);
        if (!ok)
          {
          qCritical() << "Data at column" << cid << "and row" << rid << "is not a numeric value !"
                      << " - Defaulting to 0";
          doubleValue = 0;
          }
        doubleColumn->SetValue(rid - numberOfColumnMetaDataTypes, doubleValue);
        }
      else
        {
        stringColumn->SetValue(rid - numberOfColumnMetaDataTypes, value);
        }
      }
    }

  // ColumnMetaDataTypeOfInterest
  int columnMetaDataTypeOfInterest =
      settings.value(voDelimitedTextImportSettings::ColumnMetaDataTypeOfInterest).toInt();

  // RowMetaDataTypeOfInterest
  int rowMetaDataTypeOfInterest =
      settings.value(voDelimitedTextImportSettings::RowMetaDataTypeOfInterest).toInt();

  destTable->SetColumnMetaDataTable(columnMetaData.GetPointer());
  destTable->SetRowMetaDataTable(rowMetaData.GetPointer());
  destTable->SetData(data.GetPointer());
  destTable->SetColumnMetaDataTypeOfInterest(columnMetaDataTypeOfInterest);
  destTable->SetRowMetaDataTypeOfInterest(rowMetaDataTypeOfInterest);
  destTable->SetColumnMetaDataLabels(columnMetaDataLabels.GetPointer());
  destTable->SetRowMetaDataLabels(rowMetaDataLabels.GetPointer());

  // Set column names
  voUtils::setTableColumnNames(destTable->GetData(), destTable->GetColumnMetaDataOfInterestAsString());

  // NormalizationMethod
  QString normalizationMethod =
      settings.value(voDelimitedTextImportSettings::NormalizationMethod).toString();

  // Normalize
  if (voApplication::application())
    {
    voApplication::application()->normalizerRegistry()->apply(
          normalizationMethod, destTable->GetData(), settings);
    }
}
Ejemplo n.º 9
0
vtkSmartPointer<vtkTable> LoadRotatedTable(std::string filename)
{
	/*!
	*	Read a tab deliminated text file and create a vtkTable
	*/
	if( !FileExists(filename.c_str()) )
		return NULL;

	const int MAXLINESIZE = 102400;	//Numbers could be in scientific notation in this file
	char line[MAXLINESIZE];

	//Open the file:
	ifstream inFile; 
	inFile.open( filename.c_str());
	if ( !inFile.is_open() )
		return NULL;

	vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();	
	int ct = 0;
	while ( !inFile.eof() ) //Get all values
	{
		inFile.getline(line, MAXLINESIZE);
		char * pch = strtok (line," \t");

		if( pch != NULL)
		{
			vtkSmartPointer<vtkVariantArray> column = vtkSmartPointer<vtkVariantArray>::New();
			std::string col_name = pch;
			if( col_name == "#N/A" )
			{
				std::stringstream out;
				out<< ct;
				col_name += out.str();
			}

			column->SetName( col_name.c_str() );
			pch = strtok (NULL, " \t");
			while (pch != NULL)
			{
				column->InsertNextValue(vtkVariant( atof(pch)));
				pch = strtok (NULL, " \t");
			}

			table->AddColumn(column);
			ct++;

			if( ct % 100 == 0)
			{
				std::cout<< ct<<"\t";
			}
		}
		else
		{
			break;
		}	
	}

	inFile.close();
	std::cout<< std::endl<< "LoadRotatedTable: "<<table->GetNumberOfRows()<<"\t"<< table->GetNumberOfColumns()<<endl;
	return table;
}
Ejemplo n.º 10
0
vtkSmartPointer<vtkTable> LoadTable(std::string filename)
{
	/*!
	*	Read a tab deliminated text file and create a vtkTable
	*/
	if( !FileExists(filename.c_str()) )
		return NULL;

	const int MAXLINESIZE = 102400;	//Numbers could be in scientific notation in this file
	char line[MAXLINESIZE];

	//Open the file:
	ifstream inFile; 
	inFile.open( filename.c_str() );
	if ( !inFile.is_open() )
		return NULL;

	vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();	

	//!LOAD THE HEADER INFO:
	/**Creates the vtk table header information to reference the columns by*/
	inFile.getline(line, MAXLINESIZE);
	char * pch = strtok (line," \t");
	int ct = 0;
	//int i = 0;
	//std::stringstream ss;
	while (pch != NULL)
	{
		vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
		std::string col_name = pch;
		std::replace(col_name.begin(),col_name.end(),'(','_');
		std::replace(col_name.begin(),col_name.end(),')','_');
		std::replace(col_name.begin(),col_name.end(),',','_');
		column->SetName( col_name.c_str() );
		//ss<<i++;
		//column->SetName( ss.str().c_str());
		//ss.str("");
		table->AddColumn(column);
		ct++;
		pch = strtok (NULL, " \t");
	}
	std::cout<< "Column: "<<ct<<std::endl;

	//!LOAD THE DATA:
	/*!
	* Reads all the data into table
	* Note: reads in as float but stores as vtkVariant
	*/
	inFile.getline(line, MAXLINESIZE);
	while ( !inFile.eof() ) //Get all values
	{
		vtkSmartPointer<vtkVariantArray> row = vtkSmartPointer<vtkVariantArray>::New();
		char * pch = strtok (line," \t");
		while (pch != NULL)
		{
			row->InsertNextValue( vtkVariant( atof(pch) ) );
			pch = strtok (NULL, " \t");
		}
		table->InsertNextRow(row);
		inFile.getline(line, MAXLINESIZE);
	}
	inFile.close();
	
	return table;
}
void PatternAnalysisWizardNoGUI::KPLSrun1(std::vector<int> columnsToUse){
#ifdef USE_KPLS
	//Setup up the kpls:
	KPLS *kpls = new KPLS();
	kpls->SetLatentVars(5);
	kpls->SetSigma(20);

	int num_rows = m_table->GetNumberOfRows();
	int num_cols = (int)columnsToUse.size();

	MATRIX data = kpls->GetDataPtr(num_rows, num_cols);
	VECTOR ids = kpls->GetIDPtr();
	VECTOR training = kpls->GetTrainingPtr();

	std::set<int> outcomes;
	//extract data from the table:
	for(int r=0; r<num_rows; ++r)
	{
		ids[r] = m_table->GetValue(r,0).ToDouble();
		for(int c=0; c<num_cols; ++c)
		{
			double val = m_table->GetValue(r, columnsToUse.at(c)).ToDouble();
			data[r][c] = val;
		}
		training[r] = m_table->GetValueByName(r,columnForTraining).ToDouble();
		outcomes.insert(int(training[r]));
	}

	if(outcomes.size() <= 1)
	{
		delete kpls;
		return;
	}

	kpls->InitVariables();
	kpls->ScaleData();
	kpls->Train();
	kpls->Classify();

	VECTOR predictions = kpls->GetPredictions();

	//If need to create a new column do so now:
	vtkAbstractArray * output = m_table->GetColumnByName(columnForPrediction);
	if(output == 0)
	{
		vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
		column->SetName( columnForPrediction );
		column->SetNumberOfValues( m_table->GetNumberOfRows() );
		m_table->AddColumn(column);
	}

	for(int row = 0; (int)row < m_table->GetNumberOfRows(); ++row)  
	{
		m_table->SetValueByName(row, columnForPrediction, vtkVariant(predictions[row]));
	}

	delete kpls;
#else
	std::cerr<<"Compiled without the KPLS library"<<std::endl;
#endif
}
Ejemplo n.º 12
0
// --------------------------------------------------------------------------
bool voKEGGPathway::execute()
{
  //-------------------------------------------------------
  // Get and validate parameters
  QString keggURL = QString("http://%1:%2/kegg/").arg(Visomics_KEGG_SERVER_HOSTNAME).arg(Visomics_KEGG_SERVER_PORT);

  QString pathwayID =  this->stringParameter("pathway_id");
  if (!pathwayID.startsWith("path:"))
    {
    qWarning() << "Pathway ID does not start with \"path:\"";
    return false;
    }

  // Import data table locally
  vtkExtendedTable* extendedTable =  vtkExtendedTable::SafeDownCast(this->input()->dataAsVTKDataObject());
  if (!extendedTable)
    {
    qWarning() << "Input is Null";
    return false;
    }

  //-------------------------------------------------------
  // Build vtkGraph of pathway
  vtkNew<vtkMutableDirectedGraph> graph;
    {
    graph->GetVertexData()->SetPedigreeIds(vtkSmartPointer<vtkStringArray>::New().GetPointer());
    graph->GetVertexData()->GetPedigreeIds()->SetName("PedigreeIds");

    QUrl graphURL(keggURL + "graph");
    graphURL.addQueryItem("path", pathwayID);

    QByteArray responseData;
    if(!voKEGGUtils::queryServer(graphURL, &responseData))
      {
      // Error message already printed within voKEGGUtils::queryServer()
      return false;
      }

    QScriptValue rawScriptValue;
    if(!voKEGGUtils::dataToJSON(responseData, &rawScriptValue))
      {
      // Error message already printed within voKEGGUtils::dataToJSON()
      return false;
      }

    QScriptValue pathwayScriptValue = rawScriptValue.property(0); // Only made 1 query
    for(int i = 0; i < pathwayScriptValue.property("pathway_graph").property("length").toInt32(); i++)
      {
      vtkStdString inVertexName = pathwayScriptValue.property("pathway_graph").property(i).property(0).toString().toStdString();
      vtkStdString outVertexName = pathwayScriptValue.property("pathway_graph").property(i).property(1).toString().toStdString();
      vtkIdType inVertexIndex = graph->AddVertex(vtkVariant(inVertexName));
      vtkIdType outVertexIndex = graph->AddVertex(vtkVariant(outVertexName));
      graph->AddEdge(inVertexIndex, outVertexIndex);
      }
    }
  this->setViewPrettyName("pathway_graph", "voKEGGPathwayView", QString("Graph (%1)").arg(this->stringParameter("pathway_id")));
  this->setOutput("pathway_graph", new voDataObject("pathway_graph", graph.GetPointer()));

  //-------------------------------------------------------
  // Find shortest paths between known analytes in graph
  vtkNew<vtkTable> shortestPathTable;
    {
    // Note: this implementation is for demo / proof of concept purposes.
    // To generate presentAnalytes, tt must refetch all analyte information
    // from the server, because there is no way to share data from voKEGGCompounds
    // (which should have already been run, and which will already fetch and
    // generate this same information)
    vtkNew<vtkStringArray> presentAnalyteNames;
    vtkNew<vtkStringArray> presentAnalytesIds;
    vtkNew<vtkIdTypeArray> presentAnalyteVertexIds;
      {
      vtkStringArray* analyteNames = extendedTable->GetRowMetaDataOfInterestAsString();
      QUrl compoundURL(keggURL + "compound");
      for (vtkIdType ctr = 0; ctr < analyteNames->GetNumberOfValues(); ++ctr)
        {
        compoundURL.addQueryItem("path", QString(analyteNames->GetValue(ctr)));
        }
      QByteArray responseData;
      if(!voKEGGUtils::queryServer(compoundURL, &responseData))
        {
        // Error message already printed within voKEGGUtils::queryServer()
        return false;
        }
      QScriptValue responseSV;
      if(!voKEGGUtils::dataToJSON(responseData, &responseSV))
        {
        // Error message already printed within voKEGGUtils::dataToJSON()
        return false;
        }
      for (vtkIdType ctr = 0; ctr < analyteNames->GetNumberOfValues(); ++ctr)
        {
        QScriptValue compoundSV = responseSV.property(ctr);
        if(QString::fromStdString(analyteNames->GetValue(ctr)) !=
           compoundSV.property("compound_name").toString()) // Sanity check
          {
          qWarning() << "Error: Server returned out of order results";
          return false;
          }
        for(int pathCtr = 0; pathCtr < compoundSV.property("compound_pathways").property("length").toInt32(); pathCtr++)
          {
          QString compoundPathId = compoundSV.property("compound_pathways").property(pathCtr).property(0).toString();
          if (compoundPathId == pathwayID) // The compound is included in this pathway
            {
            vtkVariant analyteId(compoundSV.property("compound_id").toString().toStdString());
            vtkIdType vertexId = graph->FindVertex(analyteId);
            if(vertexId != -1) // Some KEGG compounds may claim to be in a pathway, but have no actual vertex present
              {
              presentAnalyteNames->InsertNextValue(analyteNames->GetValue(ctr));
              presentAnalytesIds->InsertNextValue(analyteId.ToString());
              presentAnalyteVertexIds->InsertNextValue(vertexId);
              }
            break;
            }
          }
        }
      } // End presentAnalytes generation

    shortestPathTable->AddColumn(presentAnalyteNames.GetPointer());
    for(vtkIdType col = 0; col < presentAnalyteNames->GetNumberOfValues(); col++)
      {
      vtkNew<vtkStringArray> tempColumn;
      tempColumn->SetNumberOfValues(presentAnalyteNames->GetNumberOfValues());
      tempColumn->SetName(presentAnalyteNames->GetValue(col));
      shortestPathTable->AddColumn(tempColumn.GetPointer());
      }

    for(vtkIdType startCtr = 0; startCtr < presentAnalytesIds->GetNumberOfValues(); startCtr++)
      {
      vtkIdType startVertex = presentAnalyteVertexIds->GetValue(startCtr);

      // BFS to find distances (don't need Dijkstra's since edge weights are uniform)
      QHash<vtkIdType, double> distances;
      distances.insert(startVertex, 0.0);

      QQueue<vtkIdType> toVisit;
      toVisit.enqueue(startVertex);

      vtkNew<vtkAdjacentVertexIterator> adjItr;
      while(!toVisit.empty())
        {
        vtkIdType current = toVisit.dequeue();
        graph->GetAdjacentVertices(current, adjItr.GetPointer());
        while(adjItr->HasNext())
          {
          vtkIdType adj = adjItr->Next();
          if(!distances.contains(adj))
            {
            // Use only half distance, as all compounds are seperated by a reaction
            distances.insert(adj, (distances.value(current) + 0.5));
            toVisit.enqueue(adj);
            }
          }
        }

      for(vtkIdType endCtr = 0; endCtr < presentAnalytesIds->GetNumberOfValues(); endCtr++)
        {
        vtkIdType endVertex = presentAnalyteVertexIds->GetValue(endCtr);
        vtkVariant distanceString;
        if(distances.contains(endVertex))
          {
          distanceString = static_cast<int>(distances.value(endVertex));
          }
        else
          {
          distanceString = "-";
          }
        shortestPathTable->SetValue(startCtr, endCtr+1, distanceString);
        }
      }
    }
  this->setOutput("pathway_shortest", new voTableDataObject("pathway_shortest", shortestPathTable.GetPointer()));

  //-------------------------------------------------------
  // Fetch pathway map image
  QPixmap pixmap;
    {
    QUrl mapURL(keggURL + "map");
    mapURL.addQueryItem("path", pathwayID);

    QByteArray responseData;
    if(!voKEGGUtils::queryServer(mapURL, &responseData))
      {
      // Error message already printed within voKEGGUtils::queryServer()
      return false;
      }

    if (!pixmap.loadFromData(responseData))
      {
      qWarning() << "Could not load PNG image";
      return false;
      }
    }
  this->setViewPrettyName("pathway_map", "voKEGGImageView",QString("Map (%1)").arg(this->stringParameter("pathway_id")));
  this->setOutput("pathway_map", new voDataObject("pathway_map", static_cast<QVariant>(pixmap)));

  //-------------------------------------------------------
  return true;
}
void IntrinsicFeatureCalculator::GetDistanceToSurfaceMeasures(vtkSmartPointer<vtkTable> table, std::vector< ftk::Object::Point > surfacePoints)
{
	typedef itk::Image< IPixelT, 3 > InputImageType;
	typedef itk::Image< LPixelT, 3 > OutputImageType;
	typedef itk::DanielssonDistanceMapImageFilter< OutputImageType, OutputImageType > DanielssonFilterType;
	typedef itk::RescaleIntensityImageFilter< OutputImageType, OutputImageType > RescalerType;
	typedef itk::ImageFileReader< InputImageType  >  ReaderType;
	typedef itk::ImageFileWriter< InputImageType >  InputWriterType;
	typedef itk::ImageFileWriter< OutputImageType >  WriterType;
	typedef itk::LineIterator< OutputImageType > LineIteratorType;

	vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
	column->SetName( "Dist_To_Surface" );
	column->SetNumberOfValues( table->GetNumberOfRows() );
	table->AddColumn(column);	

	OutputImageType::Pointer im;
	im = OutputImageType::New();
	OutputImageType::PointType origin;
    origin[0] = 0; 
    origin[1] = 0;    
	origin[2] = 0;    
    im->SetOrigin( origin );

    OutputImageType::IndexType start;
    start[0] =   0;  // first index on X
    start[1] =   0;  // first index on Y    
	start[2] =   0;  // first index on Z    
    
	OutputImageType::Pointer temp_image = labelImage->GetItkPtr< LPixelT >(0,0);
	itk::Size<3> im_size = temp_image->GetBufferedRegion().GetSize();
	im_size[2] = 1;
  
    InputImageType::RegionType region;
    region.SetSize( im_size );
    region.SetIndex( start );
    
    im->SetRegions( region );
    im->Allocate();
    im->FillBuffer(0);
	im->Update();
	
	//copy the input image into the ITK image
	for(int p = 1; p < (int)surfacePoints.size(); ++p)
	{
		itk::Index<3> indx,indy;
		indx[0] = surfacePoints[p-1].x;
		indx[1] = surfacePoints[p-1].y;
		indx[2] = 0;
		indy[0] = surfacePoints[p].x;
		indy[1] = surfacePoints[p].y;
		indy[2] = 0;
		LineIteratorType it( im, indx, indy );
		//it.GoToBegin();
		//while(!it.IsAtEnd())
		for(it.GoToBegin(); !it.IsAtEnd(); ++it)
		{
			it.Set(255);			
		}
	}

	DanielssonFilterType::Pointer danielssonFilter = DanielssonFilterType::New();	
	WriterType::Pointer writer = WriterType::New();	
	danielssonFilter->SetInput( im );
	writer->SetFileName( "DistanceMap.tif" );
	danielssonFilter->InputIsBinaryOn();
	danielssonFilter->Update();
	OutputImageType::Pointer distMap = danielssonFilter->GetOutput();
	writer->SetInput( distMap );
	writer->Update();
	
	for(int row=0; row<(int)table->GetNumberOfRows(); ++row)
	{
		OutputImageType::IndexType indx;
		indx[0] = table->GetValue(row, 1).ToInt();
		indx[1] = table->GetValue(row, 2).ToInt();
		indx[2] = 0;
		int dist = distMap->GetPixel(indx);
		table->SetValueByName(row, "Dist_To_Surface", vtkVariant(dist));
	}



}
//Update the features in this table whose names match (sets doFeat)
//Will creat new rows if necessary:
void IntrinsicFeatureCalculator::Append(vtkSmartPointer<vtkTable> table)
{
	if(!intensityImage || !labelImage)
		return;

	//Compute features:
	typedef ftk::LabelImageToFeatures< IPixelT, LPixelT, 3 > FeatureCalcType;
	FeatureCalcType::Pointer labFilter = FeatureCalcType::New();
	if(useRegion)
	{
		labFilter->SetImageInputs( intensityImage->GetItkPtr<IPixelT>(0,intensityChannel), labelImage->GetItkPtr<LPixelT>(0,labelChannel), regionIndex, regionSize, cyto_image );
	}
	else
	{
		labFilter->SetImageInputs( intensityImage->GetItkPtr<IPixelT>(0,intensityChannel), labelImage->GetItkPtr<LPixelT>(0,labelChannel), cyto_image );
	}
	labFilter->SetLevel( needLevel() );
	if( needHistogram() )
		labFilter->ComputeHistogramOn();
	if( needTextures() )
		labFilter->ComputeTexturesOn();
	labFilter->Update();

	//Add new columns to the table (headers):
	for (int i=0; i < IntrinsicFeatures::N; ++i)
	{
		if(doFeat[i])
		{
			vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
			column->SetName( (fPrefix+IntrinsicFeatures::Info[i].name).c_str() );
			column->SetNumberOfValues( table->GetNumberOfRows() );
			table->AddColumn(column);
		}
	}

	//Now update the table:
	std::vector< FeatureCalcType::LabelPixelType > labels = labFilter->GetLabels();
	for (int i=0; i<(int)labels.size(); ++i)
	{
		FeatureCalcType::LabelPixelType id = labels.at(i);
		if(id == 0) continue;
		if(useIDs)
			if(IDs.find(id) == IDs.end()) continue;	//Don't care about this id, so skip it

		int row = -1;
		for(int r=0; r<table->GetNumberOfRows(); ++r)
		{
			if( table->GetValue(r,0) == id )
			{
				row = r;
				break;
			}
		}

		ftk::IntrinsicFeatures * features = labFilter->GetFeatures(id);

		//Must Create a new row:
		if(row == -1)
		{
			vtkSmartPointer<vtkVariantArray> nrow = vtkSmartPointer<vtkVariantArray>::New();
			for( unsigned ii=0; ii<table->GetNumberOfColumns(); ++ii )
				nrow->InsertNextValue( vtkVariant(0.0) );
			table->InsertNextRow(nrow);
			row = table->GetNumberOfRows() - 1;
			table->SetValue(row, 0, vtkVariant(id));
		}

		for (int f=0; f<IntrinsicFeatures::N; ++f)
		{
			if(doFeat[f])
				table->SetValueByName(row,(fPrefix+IntrinsicFeatures::Info[f].name).c_str(), vtkVariant(features->ScalarFeatures[f]));
		}
	}
}
//Update the features in this table whose names match (sets doFeat)
//Will create new rows if necessary:
void IntrinsicFeatureCalculator::Update(vtkSmartPointer<vtkTable> table, std::map<int, ftk::Object::Point> * cc, std::map<int, ftk::Object::Box> * bbox, vtkSmartPointer<vtkTable> NucAdjTable, int currtime)
{
	if(!intensityImage || !labelImage)
		return;

	if(table)
	{
		//Determine needed features:
		for(int i=0; i<IntrinsicFeatures::N; ++i)
		{
			std::string name = fPrefix+IntrinsicFeatures::Info[i].name;
			vtkAbstractArray * arr = table->GetColumnByName( name.c_str() );
			if(arr == NULL || arr == 0)
				doFeat[i] = false;
			else
				doFeat[i] = true;
		}
	}

	//Compute features:
	typedef ftk::LabelImageToFeatures< IPixelT, LPixelT, 3 > FeatureCalcType;
	FeatureCalcType::Pointer labFilter = FeatureCalcType::New();
	if(useRegion)
	{
		labFilter->SetImageInputs( intensityImage->GetItkPtr<IPixelT>(0,intensityChannel), labelImage->GetItkPtr<LPixelT>(0,labelChannel), regionIndex, regionSize );
	}
	else
	{
		labFilter->SetImageInputs( intensityImage->GetItkPtr<IPixelT>(0,intensityChannel), labelImage->GetItkPtr<LPixelT>(0,labelChannel) );
	}
	
	if(table)
	{
		labFilter->SetLevel( needLevel() );
		if( needHistogram() )
			labFilter->ComputeHistogramOn();
		if( needTextures() )
			labFilter->ComputeTexturesOn();
	}
	else
	{
		labFilter->SetLevel(3);  //modified by yanbin from 2 to 3 ;
		labFilter->ComputeHistogramOff();
		labFilter->ComputeTexturesOff();
	}

	labFilter->Update();

	//Update the Nuclear Adjacency Table
	if(NucAdjTable)
	{
		FeatureCalcType::Pointer AdjFilter = FeatureCalcType::New();
		AdjFilter->SetImageInputs( intensityImage->GetItkPtr<IPixelT>(0,intensityChannel), labelImage->GetItkPtr<LPixelT>(0,labelChannel) );
		AdjFilter->GetAdjacency();
		std::set<unsigned short>::iterator it;
		for(it=IDs.begin(); it!=IDs.end(); ++it)
		{
			std::vector<unsigned short> conIDs = AdjFilter->GetContactNeighbors(*it);
			if(conIDs.size()>0)
			{
				for(unsigned int i=0 ; i<conIDs.size() ; ++i)
				{
					if(conIDs[i] == 0) continue;
					vtkSmartPointer<vtkVariantArray> nextrow = vtkSmartPointer<vtkVariantArray>::New();
					nextrow->InsertNextValue(*it);
					nextrow->InsertNextValue(conIDs[i]);
					NucAdjTable->InsertNextRow(nextrow);
				}
			}
		}
	}
	//Now update the table:
	std::vector< FeatureCalcType::LabelPixelType > labels = labFilter->GetLabels();
	for (int i=0; i<(int)labels.size(); ++i)
	{
		FeatureCalcType::LabelPixelType id = labels.at(i);
		if(id == 0) continue;
		if(useIDs)
			if(IDs.find(id) == IDs.end()) continue;	//Don't care about this id, so skip it

		ftk::IntrinsicFeatures * features = labFilter->GetFeatures(id);

		if(table)
		{
			int row = -1;
			for(int r=0; r<table->GetNumberOfRows(); ++r)
			{
				if( table->GetValue(r,0) == id )
				{
					row = r;
					break;
				}
			}

			//Must Create a new row:
			if(row == -1)
			{
				vtkSmartPointer<vtkVariantArray> nrow = vtkSmartPointer<vtkVariantArray>::New();
				for( unsigned ii=0; ii<table->GetNumberOfColumns(); ++ii )
					nrow->InsertNextValue( vtkVariant(0.0) );
				table->InsertNextRow(nrow);
				row = table->GetNumberOfRows() - 1;
				table->SetValue(row, 0, vtkVariant(id));
			}

			//Update table:
			table->SetValueByName(row,"centroid_x", vtkVariant((int)features->Centroid[0]));
			table->SetValueByName(row,"centroid_y", vtkVariant((int)features->Centroid[1]));
			if( labelImage->GetImageInfo()->numZSlices > 2 )
				table->SetValueByName(row,"centroid_z", vtkVariant((int)features->Centroid[2]));
			else
				table->SetValueByName(row,"centroid_z", vtkVariant(0));

//			table->SetValueByName(row,"num_z_slices", vtkVariant((int)intensityImage->GetImageInfo()->numZSlices));
			int col_count = 0;
			for (int f=0; f<IntrinsicFeatures::N; ++f)
			{
				if(doFeat[f])
				{
					table->SetValueByName(row,(fPrefix+IntrinsicFeatures::Info[f].name).c_str(), vtkVariant(features->ScalarFeatures[f]));
					++col_count;
				}
			}
			std::vector< std::vector<double> > zernVec = labFilter->GetZernikeMoments(id);
			for(int i=0; i<(int)zernVec.size(); ++i)
			{
				for(int j=0; j<(int)zernVec.at(i).size(); ++j)
				{
					table->SetValue(row, ++col_count ,vtkVariant(zernVec.at(i).at(j)) );
				}
			}
		}

		//Update centroids:
		if(cc)
		{
			Object::Point c;
			c.x = (int)features->Centroid[0];
			c.y = (int)features->Centroid[1];
			if( intensityImage->GetImageInfo()->numZSlices > 2 )
				c.z = (int)features->Centroid[2];
			else
				c.z = 0;
			c.t = currtime;
			(*cc)[(int)id] = c;
		}

		//Update bounding boxes:
		if(bbox)
		{
			Object::Box b;
			b.min.x = (int)features->BoundingBox[0];
			b.max.x = (int)features->BoundingBox[1];
			b.min.y = (int)features->BoundingBox[2];
			b.max.y = (int)features->BoundingBox[3];
			if( intensityImage->GetImageInfo()->numZSlices > 2 )
			{
				b.min.z = (int)features->BoundingBox[4];
				b.max.z = (int)features->BoundingBox[5];
			}
			else
			{
				b.min.z = 0;
				b.max.z = 0;
			}
			b.min.t = currtime;
			b.max.t = currtime;
			(*bbox)[(int)id] = b;
		}
	}
}
//Compute features turned ON in doFeat and puts them in a new table
vtkSmartPointer<vtkTable> IntrinsicFeatureCalculator::Compute(void)
{
	vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();

	if(!intensityImage || !labelImage)
	{
		return table;
	}

	//Compute features:
	typedef ftk::LabelImageToFeatures< IPixelT, LPixelT, 3 > FeatureCalcType;
	FeatureCalcType::Pointer labFilter = FeatureCalcType::New();
	if(useRegion)
	{
		labFilter->SetImageInputs( intensityImage->GetItkPtr<IPixelT>(0,intensityChannel), labelImage->GetItkPtr<LPixelT>(0,labelChannel), regionIndex, regionSize );
	}
	else
	{
		labFilter->SetImageInputs( intensityImage->GetItkPtr<IPixelT>(0,intensityChannel), labelImage->GetItkPtr<LPixelT>(0,labelChannel) );
	}
	//labFilter->SetLevel( needLevel() );
	labFilter->SetLevel( 3); //////////////////////////modified by Yanbin from 3 to 2;
	labFilter->ComputeSurfaceOn();
	if( needHistogram() )
		labFilter->ComputeHistogramOn();
	if( needTextures() )
		labFilter->ComputeTexturesOn();
	labFilter->Update();

	//Init the table (headers):
	vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
	column->SetName( "ID" );
	table->AddColumn(column);
	
	column = vtkSmartPointer<vtkDoubleArray>::New();
	column->SetName( "centroid_x" );
	table->AddColumn(column);

	column = vtkSmartPointer<vtkDoubleArray>::New();
	column->SetName( "centroid_y" );
	table->AddColumn(column);

	column = vtkSmartPointer<vtkDoubleArray>::New();
	column->SetName( "centroid_z" );
	table->AddColumn(column);

//	column = vtkSmartPointer<vtkDoubleArray>::New();
//	column->SetName( "num_z_slices" );
//	table->AddColumn(column);
//
	for (int i=0; i < IntrinsicFeatures::N; ++i)
	{
		if(doFeat[i])
		{
			column = vtkSmartPointer<vtkDoubleArray>::New();
			column->SetName( (fPrefix+IntrinsicFeatures::Info[i].name).c_str() );
			table->AddColumn(column);
		}
	}

	std::vector< FeatureCalcType::LabelPixelType > labels = labFilter->GetLabels();

	for (int i=0; i<(int)labels.size(); ++i)
	{
		FeatureCalcType::LabelPixelType id = labels.at(i);
		if(id == 0) continue;
		if(useIDs)
			if(IDs.find(id) == IDs.end()) continue;	//Don't care about this id, so skip it
		std::vector< std::vector<double> > testVec = labFilter->GetZernikeMoments(id);
		for(int i=0; i<(int)testVec.size(); ++i)
		{
			std::stringstream ss1;
			ss1 << i;
			for(int j=0; j<(int)testVec.at(i).size(); ++j)
			{
				column = vtkSmartPointer<vtkDoubleArray>::New();
				std::stringstream ss2;
				ss2 << ((i%2)+(2*j));
				column->SetName( ("Zern_"+ss1.str()+"_"+ss2.str()).c_str() );
				table->AddColumn(column);
				std::cout<<"computing zernike"<<std::endl;
			}
		}
	}

	//Now populate the table:
	//std::vector< FeatureCalcType::LabelPixelType > labels = labFilter->GetLabels();
	for (int i=0; i<(int)labels.size(); ++i)
	{
		FeatureCalcType::LabelPixelType id = labels.at(i);
		if(id == 0) continue;
		if(useIDs)
			if(IDs.find(id) == IDs.end()) continue;	//Don't care about this id, so skip it

		ftk::IntrinsicFeatures * features = labFilter->GetFeatures(id);
		vtkSmartPointer<vtkVariantArray> row = vtkSmartPointer<vtkVariantArray>::New();
		row->InsertNextValue( vtkVariant(id) );
		row->InsertNextValue( vtkVariant((int)features->Centroid[0]) );
		row->InsertNextValue( vtkVariant((int)features->Centroid[1]) );
		if( intensityImage->GetImageInfo()->numZSlices > 2 )
			row->InsertNextValue( vtkVariant((int)features->Centroid[2]) );
		else
			row->InsertNextValue( vtkVariant(0));
//		row->InsertNextValue( vtkVariant((int)intensityImage->GetImageInfo()->numZSlices) );
		for (int i=0; i<IntrinsicFeatures::N; ++i)
		{
			if(doFeat[i])
				row->InsertNextValue( vtkVariant(features->ScalarFeatures[i]) );
		}
		std::vector< std::vector<double> > zernVec = labFilter->GetZernikeMoments(id);
		for(int i=0; i<(int)zernVec.size(); ++i)
		{
			for(int j=0; j<(int)zernVec.at(i).size(); ++j)
			{
				row->InsertNextValue( vtkVariant(zernVec.at(i).at(j)) );
			}
		}
		table->InsertNextRow(row);
	}
	return table;
}
//Update the features in this table whose names match (sets doFeat)
void AssociativeFeatureCalculator::Append(vtkSmartPointer<vtkTable> table)
{
	//Compute features:
	ftk::NuclearAssociationRules *assoc;
	if( inputs_set ){
		assoc = new ftk::NuclearAssociationRules("",0,lab_im, inp_im);
		assoc->AddAssociation( input_association->GetRuleName(), "", input_association->GetOutDistance(), input_association->GetInDistance(),	input_association->IsUseWholeObject(), input_association->IsUseBackgroundSubtraction(), input_association->IsUseMultiLevelThresholding(), input_association->GetNumberOfThresholds(), input_association->GetNumberIncludedInForeground(), input_association->GetAssocType(), input_association->get_path() );
	}
	else{
		assoc = new ftk::NuclearAssociationRules("",0);
		assoc->ReadRulesFromXML(inFilename);
	}
	assoc->PrintSelf();
	assoc->Compute();	

	//Init the table (headers):
	for (int i=0; i < assoc->GetNumofAssocRules(); ++i)
	{
		vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
		column->SetName( (fPrefix+assoc->GetAssociationRules().at(i).GetRuleName()).c_str() );
		column->SetNumberOfValues( table->GetNumberOfRows() );
		table->AddColumn(column);
	}

	//Now update the table:
	std::vector<unsigned short> labels = assoc->GetLabels();
	float** vals = assoc->GetAssocFeaturesList();
	//#pragma omp parallel for num_threads(4)
	for (int i=0; i<(int)labels.size(); ++i)
	{
		unsigned short id = labels.at(i);
		if(id == 0) continue;

		int row = -1;
		for(int r=0; r<table->GetNumberOfRows(); ++r)
		{
			if( table->GetValue(r,0) == id )
			{
				row = r;
				break;
			}
		}

		if(row == -1) continue;

		for (int f=0; f<assoc->GetNumofAssocRules(); ++f)
		{
			table->SetValueByName(row,(fPrefix+assoc->GetAssociationRules().at(f).GetRuleName()).c_str(), vtkVariant(vals[f][i]));
		}
	}
	delete assoc;
}
//****************************************************************************
// Append Segmentation Model
//****************************************************************************
void PatternAnalysisWizard::appendModel(vtkSmartPointer<vtkTable> mod_table, QString filename)
{
	int r = mod_table->GetValue((int)mod_table->GetNumberOfRows()-1, (int)mod_table->GetNumberOfColumns()-1).ToInt();
   	for(int row = 0; row < (int)m_table->GetNumberOfRows(); ++row)
	{		
		vtkSmartPointer<vtkVariantArray> model_data1 = vtkSmartPointer<vtkVariantArray>::New();
		for(int c = 0;c<(int)mod_table->GetNumberOfColumns();++c)
		{
			 std::string mod_column = mod_table->GetColumnName(c);
			 if(mod_column.compare("Class") == 0)
			 {
				 for(int col=((int)m_table->GetNumberOfColumns())-1; col>=0; --col)
				{	
					std::string current_column = m_table->GetColumnName(col);
					if(current_column.find("prediction") != std::string::npos )
					{
						model_data1->InsertNextValue(m_table->GetValue(row, col));
						break;
					}	
				}
			 }

			 else
			 {
		        for(int d=0; d<(int)m_table->GetNumberOfColumns(); ++d)
		        {
			         std::string m_column = m_table->GetColumnName(d);
			         if( m_column.compare(mod_column) == 0)
				     {
					     if(mod_column.compare("ID") == 0)
						 {
							 int id = r + m_table->GetValue(row,d).ToInt();
							 model_data1->InsertNextValue(vtkVariant(id));
						 }
						 else
							 model_data1->InsertNextValue(m_table->GetValue(row,d));
				         break;
				     }
		         }
			 }
		}
		mod_table->InsertNextRow(model_data1);
	}
	//*********************************************************************
	//Save Model
	std::string Filename = filename.toStdString();
	
	//This function writes the features to a text file
	ofstream outFile; 
	outFile.open(Filename.c_str(), ios::out | ios::trunc );
	if ( !outFile.is_open() )
	{
		std::cerr << "Failed to Load Document: " << outFile << std::endl;
		return;
	}
	//Write the headers:
	for(int c=0; c<mod_table->GetNumberOfColumns(); ++c)
	{
		outFile << mod_table->GetColumnName(c) << "\t";
	}
	outFile << "\n";
	//Write out the features:
	std::string current_column;
	for(int row = 0; row < mod_table->GetNumberOfRows(); ++row)
	{
		for(int c=0; c < mod_table->GetNumberOfColumns(); ++c)
		{
			std::stringstream out;
			current_column = mod_table->GetColumnName(c);
			if((current_column.compare("ID") == 0) || (current_column.compare("Class") == 0))
				out << std::fixed << mod_table->GetValue(row,c).ToInt();
			else
	            out << std::setprecision(3) << std::fixed << mod_table->GetValue(row,c).ToFloat();
	        outFile << out.str() << "\t";
		}
		outFile << "\n";
	}
	outFile.close();
    //******************************************************************************************

}