Hi Donna,

Thanks. I will look at the code and I let you know if I find something.

Mateus

Donna Dierker wrote:

Hi Mateus,

It's true the top cluster is mostly dense, but look at the node I've highlighed in red in the attached capture. I wonder whether nodes like this that "cinch" the cluster cause the algorithm to give up.

Attached is some code I dug out of the source that might be what Caret is actually using. (John would know for sure.) Maybe it will prove helpful in deciphering what is the bottleneck, so to speak.

On 01/26/2007 07:14 AM, Mateus Joffily wrote:

Hi Donna,

I replicated your probelm exactly with the roi.zip archive you uploaded. It contained only the flat coord and cut topo; have you tried using the fiducial coord with closed topo? It may not help, but it's worth a try.


Yes, the problem persists.


Although the clusters using metric2 appear smaller in area than the metric1 clusters, the nodes within the metric2 clusters are denser, which probably is a factor. See the attached captures, shows the dense metric 2 clusters and the sparser metric 1 clusters, using drawing mode: Links (No Backside) on the D/C surface misc menu. The top two clusters are only a single tile wide, so I'm not surprised Caret would have trouble drawing a border around them. The two bottom ones also have places where they're only a tile wide, so maybe that's the problem. If so, and switching coord/topo combos fails, then I"m not sure what else to suggest.


Yes, probably the number of tiles is a limitation for drawing the borders. I see that borders are usualy not drawn around single tile metrics. However, I have other metrics with denser clusters that it doesn't draw the border neither (compare the top cluster (no border) with the bottom cluster (cyan border) in the attached capture). May be there is some other reason too... I will think a bit more about the problem and, if I find something new, I will let you know.

Thanks a lot for your help,
Mateus


Doing a very small amount of metric smoothing (Average neighbors, 1 iteration, strength 1.0) and reducing the threshold a tad would probably help (primarily just making the clusters larger), but I'm guessing this is something you'd be very hesitant to do.

On 01/25/2007 08:33 AM, Mateus Joffily wrote:

Hi Donna,

I restarted Caret and I created a new Spec file, including only the topology, flat coordinates, metric and surface shape files, and the problem persists. I did the following tests until now:

1) I tried the same operation, selecting only one of the clusters for which the program didn't draw borders before, but the program complains "No clusters were found".

2) I tried the same operation with another metric that has even smaller cluster, and the program draws the borders correctly.

3) I tried some other operations on the selected nodes (e.g. Assign metric column to selected nodes, and Statistical report), and the program works fine for every cluster. Only 'Create Borders Around Clusters' doesn't work.

I uploaded my new Spec file (roi.zip) with the two metrics included ('metric1': problematic one; and 'metric2': with smaller clusters that works fine). If you have any other idea about what can be the problem...

Thank you very much,
Mateus


Donna Dierker wrote:

The only thing I can think to try is to restart Caret and repeat your selection of all nodes within threshold 1.0 to 50000.0. I can see from your capture that you did this and your green nodes include clusters for which it didn't draw borders. My only guess is that perhaps somehow the create borders is still acting on a previous nodes connected to node number 33651 selection, even though this radio button isn't selected (and the green nodes show select nodes was pressed with All nodes within threshold selected). Restarting simply removes any previous selections, if there is a bug lurking here.

Otherwise, my only other guess is that Caret has a minimum area for clusters, before it will generate a border around it, and the smaller ones fall below that threshold. I'm not aware of such a limit.

If you upload your spec file (including coord, topo, and metric), I can see if my luck is any better than yours:

http://pulvinar.wustl.edu/cgi-bin/upload.cgi

On 01/24/2007 10:55 AM, Mateus Joffily wrote:

Hi,

I am trying to use 'Surface Region of Interest' to create borders around metric clusters. The nodes on the surface are correctly selected, but when I select 'Create Borders Around Clusters' only one of the clusters is surrounded by a border. I have tried the same operation with other metric columns and the program seems to work fine. I don't know why, for this specific metric, some clusters are left out. I am attaching an image of caret windows. Any suggestion is well appreciated.

Thanks,
Mateus



------------------------------------------------------------------------

------------------------------------------------------------------------

/*LICENSE_START*/
/*
*  Copyright 1995-2002 Washington University School of Medicine
*
*  http://brainmap.wustl.edu
*
*  This file is part of CARET.
*
*  CARET 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.
*
*  CARET 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 CARET; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*/
/*LICENSE_END*/

#include <iostream>

#include "BorderFile.h"
#include "BrainModelBorderSet.h"
#include "BrainModelSurface.h"
#include "BrainModelSurfaceClusterToBorderConverter.h"
#include "BrainSet.h"
#include "BrainSetNodeAttribute.h"
#include "DebugControl.h"
#include "TopologyFile.h"
#include "TopologyHelper.h"

/**
* constructor.
*/
BrainModelSurfaceClusterToBorderConverter::BrainModelSurfaceClusterToBorderConverter(
                                                           BrainSet* bs,
                                                           BrainModelSurface* 
bmsIn,
                                                           TopologyFile* tfIn,
                                                           const QString& 
borderNameIn,
                                                           const 
std::vector<bool>& inputNodeClusterFlagIn)
  : BrainModelAlgorithm(bs)
{
  bms = bmsIn;
  topologyFile = tfIn;
  borderName = borderNameIn;
  numberOfBordersCreated = 0;
inputNodeClusterFlag = inputNodeClusterFlagIn;
}

/**
* destructor.
*/
BrainModelSurfaceClusterToBorderConverter::~BrainModelSurfaceClusterToBorderConverter()
{
}

/**
* execute the algorithm.
*/
void BrainModelSurfaceClusterToBorderConverter::execute() throw (BrainModelAlgorithmException)
{
  //
  // Make sure nodes are selected
  //
  if (std::count(inputNodeClusterFlag.begin(), inputNodeClusterFlag.end(), true) 
<= 0) {
     throw BrainModelAlgorithmException("No nodes are selected.h");
  }
//
  // Check inputs
  //
  if (bms == NULL) {
     throw BrainModelAlgorithmException("Surface is invalid (NULL).");
  }
//
  // Check surface for nodes
  //
  const int numNodes = bms->getNumberOfNodes();
  if (numNodes <= 0) {
     throw BrainModelAlgorithmException("Surface has no nodes.");
  }
  if (static_cast<int>(inputNodeClusterFlag.size()) != numNodes) {
     throw BrainModelAlgorithmException("Cluster node flags size is not equal to 
number of nodes.");
  }
//
  // Check surface for topology
  //
  if (topologyFile == NULL) {
     topologyFile = bms->getTopologyFile();
     if (topologyFile == NULL) {
        throw BrainModelAlgorithmException("Surface has no topology.h");
     }
  }

  //
  // Index of surface
  const int modelIndex = bms->getBrainModelIndex();
  if (modelIndex < 0) {
     throw BrainModelAlgorithmException("Surface has invalid brain model 
index.");
  }
//
  // Get the topology helper with node info sorted
  //
  topologyHelper = (TopologyHelper*)topologyFile->getTopologyHelper(false, 
true, true);
//
  // Keep track of each node's status
  //
  nodeStatus.resize(numNodes);
  std::fill(nodeStatus.begin(), nodeStatus.end(), STATUS_OUTSIDE);
//
  // Find nodes of interest (are metric but have neighbors not metric - 
boundary of cluster)
  //
  for (int i = 0; i < numNodes; i++) {
     //
     // Is node potentially in a cluster
     //
     if (inputNodeClusterFlag[i]) {
     //if (bsnc->getNodeColorSource(modelIndex, i) == colorSource) {
        //
        // Flag as inside the cluster
        //
        nodeStatus[i] = STATUS_INSIDE;
//
        // Get neighbors
        //
        int numNeighbors = 0;
        const int* neighbors = topologyHelper->getNodeNeighbors(i, 
numNeighbors);
        for (int j = 0; j < numNeighbors; j++) {
           //
           // Is it on the boundary of a cluster
           //
           if (inputNodeClusterFlag[neighbors[j]] == false) {
           //if (bsnc->getNodeColorSource(modelIndex, neighbors[j]) != 
colorSource) {
              nodeStatus[i] = STATUS_BOUNDARY;
              break;
           }
        }
     }
  }

/* //
  // Highlight nodes
  //
brainSet->clearNodeHighlightSymbols(); for (int i = 0; i < numNodes; i++) {
     if (nodeStatus[i] == STATUS_BOUNDARY) {
        BrainSetNodeAttribute* bna = brainSet->getNodeAttributes(i);
        //if (i == startingNode) {
        //   bna->setHighlighting(BrainSetNodeAttribute::HIGHLIGHT_NODE_REMOTE);
        //}
        //else {
           bna->setHighlighting(BrainSetNodeAttribute::HIGHLIGHT_NODE_LOCAL);
        //}
     }
  }
*/
for (int startNode = 0; startNode < numNodes; startNode++) {
     //
     // Clean up cluster nodes with zero or one neighbor
     //
     cleanupClusterNodes();

     //
     // Find a starting node (3 consecutive nodes that each have two boundary 
neighbors)
     //
     int startingNode = -1;
     int firstNode = -1;
     int secondNode = -1;
     for (int i = startNode; i < numNodes; i++) {
        startNode = i;
        if (nodeStatus[i] == STATUS_BOUNDARY) {
           //
           // Has only two neighbors ?
           //
           if (getBoundaryNeighborCount(i) == 2) {
              if (DebugControl::getDebugOn()) {
                 std::cout << "Examining Node: " << i << std::endl;
              }
//
              // Each of these two neighbors has only two neighbors
              //
              bool valid = true;
              int numNeighbors = 0;
              const int* neighbors = topologyHelper->getNodeNeighbors(i, 
numNeighbors);
              for (int j = 0; j < numNeighbors; j++) {
                 if (nodeStatus[neighbors[j]] == STATUS_BOUNDARY) {
                    if (getBoundaryNeighborCount(neighbors[j]) != 2) {
                       valid = false;
                       break;
                    }
                    else {
                       if (firstNode < 0) {
                          firstNode = neighbors[j];
                       }
                       else if (secondNode < 0) {
                          secondNode = neighbors[j];
                       }
                    }
                 }
              }
if (valid) {
                 startingNode = i;
                 break;
              }
           }
        }
     }
//
     // For searching
     //
     int node = -1;
     int previousNode = -1;
if ((firstNode >= 0) && (secondNode >= 0)) {
        //
        // Get neighors for first node
        //
        int numNeighbors = 0;
        const int* neighbors = topologyHelper->getNodeNeighbors(firstNode, 
numNeighbors);
//
        // Neighbors should be CCW
        //
        for (int i = 0; i < numNeighbors; i++) {
           //
           // Find the starting node
           //
           if (neighbors[i] == startingNode) {
              //
              // Get next neighbor after starting node
              //
              int next = i + 1;
              if (next >= numNeighbors) {
                 next = 0;
              }
              const int nextNeighbor = neighbors[next];
              if (nodeStatus[nextNeighbor] == STATUS_OUTSIDE) {
                 previousNode = firstNode;
                 node = startingNode;
              }
              else {
                 previousNode = startingNode;
                 node = firstNode;
              }
              break;
           }
        }
     }
if (DebugControl::getDebugOn()) {
        std::cout << "Start Node: " << previousNode << std::endl;
        std::cout << "2nd Node:   " << node << std::endl;
     }
//
     // Want to move clockwise around the boundary, note that nodes sorted 
counter-clockwise
     //
     if ((previousNode >= 0) && (node >= 0)) {
        const int originalNode = previousNode;
std::vector<int> borderNodes; borderNodes.push_back(previousNode);

        while ((node != originalNode) && (node >= 0)) {
           borderNodes.push_back(node);
//
           // Get neighbors for first node
           //
           int numNeighbors = 0;
           const int* neighbors = topologyHelper->getNodeNeighbors(node, 
numNeighbors);
bool foundNextNode = false;
           for (int j = 0; j < numNeighbors; j++) {
              //
              // Found previous node that is part of border
              //
              if (neighbors[j] == previousNode) {
                 //
                 // Find next clockwise neighbor that is a boundary node
                 //
                 int prev = j - 1;
                 for (int iters = 0; iters < numNeighbors; iters++) {
                    if (prev < 0) {
                       prev = numNeighbors - 1;
                    }
//
                    // Is this neighbor a boundary node?
                    //
                    if (nodeStatus[neighbors[prev]] == STATUS_BOUNDARY) {
                       //
                       // Use it and continue
                       //
                       previousNode = node;
                       node = neighbors[prev];
                       foundNextNode = true;
                       break;  // get out of for (int iters... loop
                    }
                    else {
                       prev--;
                    }
                 }
                 break;  // get out of (for int j... loop
              }
           }
//
           // Failure to find next node ?
           //
           if (foundNextNode == false) {
              node = -1;
           }
        }

        //
        // Were node's found
        //
        if (borderNodes.size() > 2) {
           //
           // If last node is connected to first, add first node so border 
closes.
           //
           const int lastNode = borderNodes[borderNodes.size() - 1];
           int numNeighbors = 0;
           const int* neighbors = 
topologyHelper->getNodeNeighbors(borderNodes[0], numNeighbors);
           for (int nn = 0; nn < numNeighbors; nn++) {
              if (neighbors[nn] == lastNode) {
                 borderNodes.push_back(borderNodes[0]);
              }
           }
//
           // Create a border
           //
           CoordinateFile* cf = bms->getCoordinateFile();
           Border border;
           border.setName(borderName);
           if (DebugControl::getDebugOn()) {
              std::cout << "Border Nodes: " << std::endl;
           }
           for (unsigned int m = 0; m < borderNodes.size(); m++) {
              nodeStatus[borderNodes[m]] = STATUS_WAS_BOUNDARY;
              if (DebugControl::getDebugOn()) {
                 std::cout << "   " << borderNodes[m] << std::endl;
              }
              const float* xyz = cf->getCoordinate(borderNodes[m]);
              border.addBorderLink(xyz);
           }
           if (DebugControl::getDebugOn()) {
              std::cout << std::endl;
           }
//
           // Get the border set
           //
           BrainModelBorderSet* bmbs = brainSet->getBorderSet();
//
           // Add the border to the border set
           //
           BorderFile bf;
           bf.addBorder(border);
           bmbs->copyBordersFromBorderFile(bms, &bf);
numberOfBordersCreated++;
        } // if (borderNodes.empty()...
} } // for (int startNode = 0... if (DebugControl::getDebugOn()) {
     std::cout << "Borders Created: " << numberOfBordersCreated << std::endl;
  }
}

/**
* cleanup cluster nodes such as those with one or zero neighbors.
*/
void BrainModelSurfaceClusterToBorderConverter::cleanupClusterNodes()
{
  const int numNodes = bms->getNumberOfNodes();
//
  // Check for nodes that might be in cluster but should be ignored.
  // May need to check multiple times if nodes are removed.
  //
  bool checkAgain = true;
  while (checkAgain) {
     checkAgain = false;
for (int i = 0; i < numNodes; i++) {
        if (nodeStatus[i] == STATUS_BOUNDARY) {
           //
           // Count its neighbors that are part of cluster boundary
           //
           const int validCount = getBoundaryNeighborCount(i);
//
           // If node has 0 or 1 neighbors in cluster, do not use it
           //
           if (validCount <= 1) {
              nodeStatus[i] = STATUS_OUTSIDE;
              checkAgain = true;
           }
        }
     }
  }
}
/**
* get the boundary neighor count for a node.
*/
int BrainModelSurfaceClusterToBorderConverter::getBoundaryNeighborCount(const int nodeNumber) const
{
  int validCount = 0;
  int numNeighbors = 0;
  const int* neighbors = topologyHelper->getNodeNeighbors(nodeNumber, 
numNeighbors);
  for (int j = 0; j < numNeighbors; j++) {
     if (nodeStatus[neighbors[j]] == STATUS_BOUNDARY) {
        validCount++;
     }
  }
return validCount; }
------------------------------------------------------------------------

_______________________________________________
caret-users mailing list
caret-users@brainvis.wustl.edu
http://pulvinar.wustl.edu/mailman/listinfo/caret-users

Reply via email to