From ba4c49dfef1380f6a5d84129561dc24466c15fa1 Mon Sep 17 00:00:00 2001
From: Mark Jenkinson <mark@fmrib.ox.ac.uk>
Date: Thu, 9 Nov 2000 17:49:06 +0000
Subject: [PATCH] Implemented efficient sort

---
 cluster.cc | 72 ++++++++++++++++++++++++++++--------------------------
 1 file changed, 37 insertions(+), 35 deletions(-)

diff --git a/cluster.cc b/cluster.cc
index dc03caf..4daa402 100644
--- a/cluster.cc
+++ b/cluster.cc
@@ -9,17 +9,18 @@
 #include "fmribmain.h"
 #include "newimageall.h"
 #include <vector>
+#include <algorithm>
 
 using namespace NEWIMAGE;
 
 void print_usage(char *argv[])
 {
   cerr << "Usage: " << argv[0] << " <input file> <output file> "  
-       << "<threshold> <output_format> [-fe]" << endl;
+       << "<threshold> <output_format> [options]" << endl;
   cerr << "[-f] : threshold is fractional (of robust range) instead of "
        << "absolute"<<endl;
-  cerr << "[-e] : used only edge connections (6-way) instead of "
-       << "corner connections (26-way)"<<endl;
+  cerr << "[-6,18,26] : number of connections at each point (default is 26)"
+       <<endl;
   cerr << "If threshold is -ve then binarization is inverted"<<endl;
   cerr << "Output formats: the output intensity signifies:"<<endl;
   cerr << "0 - size"<<endl;
@@ -67,21 +68,19 @@ void get_stats(const volume<int>& labelim, const volume<T>& origim,
 
 void get_sizeorder(const std::vector<int>& size, std::vector<int>& sizeorder) 
 {
-  // A BAD O(N^2) SORTING ALGORITHM...
-  int labelnum=size.size()-1, maxidx=0, maxsize=0;
-  sizeorder.resize(labelnum,0);
-  std::vector<int> sizecopy(size);
-  for (int n=labelnum; n>=1; n--) {
-    maxidx=0;
-    maxsize=0;
-    for (int m=1; m<=labelnum; m++) {
-      if (sizecopy[m]>maxsize) {
-	maxidx = m;
-	maxsize = sizecopy[m];
-      }
-    }
-    sizecopy[maxidx]=0;
-    sizeorder[maxidx] = n;
+  // find order of labels so that sizes are in *ascending* order
+  int length=size.size()-1;
+  std::vector<pair<int, int> > sortlist(length+1);
+  for (int n=0; n<=length; n++) {
+    sortlist[n] = pair<int, int>(size[n],n);
+  }
+  sortlist[0].first = 0;  // force the background component to be in 0th posn
+  sort(sortlist.begin(),sortlist.end());  // O(N.log(N))
+
+  // second part of pair is now the prior-index of the sorted values
+  sizeorder.resize(length+1,0);
+  for (int n=0; n<=length; n++) {
+    sizeorder[sortlist[n].second] = n;    // maps old index to new
   }
 }
 
@@ -113,29 +112,32 @@ int fmrib_main(int argc, char *argv[])
     volume<T> vin;
     read_volume(vin,argv[1]);
     
-    // threshold the volume
-    bool invert=false;
-    float th;
-    string opt1="", opt2="", opt="";
-    if (argc>=6) { opt = argv[5]; }
-    if (opt=="-f") { opt1="-f"; }
-    else if (opt=="-e") { opt2="-e"; }
-    else if ( (opt=="-fe") || (opt=="-ef") ) { opt1="-f"; opt2="-e"; }
-    else if (opt!="") { 
-      cerr << "Unrecognised option "<<opt<<endl<<endl;
-      print_usage(argv); 
-      return -1;
+    // parse the options
+    bool invert=false, fractionalthresh=false;
+    int numconnected=26;
+
+    for (int n=5; n<argc; n++) {
+      string opt=argv[n];
+      if (opt=="-f") { fractionalthresh=true; }
+      else if (opt=="-6") { numconnected=6; }
+      else if (opt=="-18") { numconnected=18; }
+      else if (opt=="-26") { numconnected=26; }
+      else { 
+	cerr << "Unrecognised option "<<opt<<endl<<endl;
+	print_usage(argv); 
+	return -1;
+      }
     }
 
-    bool use_corners=true;
-    if (opt2=="-e") { use_corners=false; }
-
+    // threshold the volume
+    float th;
     th = atof(argv[3]);
     if (th<0.0) { 
       invert=true;
       th=-th;
     }
-    if ( opt1=="-f" ) {
+
+    if ( fractionalthresh ) {
       float frac = th;
       th = frac*(vin.robustmax() - vin.robustmin()) + vin.robustmin();
     }
@@ -143,7 +145,7 @@ int fmrib_main(int argc, char *argv[])
     if (invert) { vin = ((T) 1) - vin; }
     
     // Find the connected components
-    labelim = connected_components(vin,use_corners);
+    labelim = connected_components(vin,numconnected);
     
     // process according to the output format
     read_volume(vin,argv[1]);  // re-read the original volume
-- 
GitLab