2 * clustersplitcommand.cpp
5 * Created by westcott on 5/19/10.
6 * Copyright 2010 Schloss Lab. All rights reserved.
10 #include "clustersplitcommand.h"
11 #include "readcluster.h"
12 #include "splitmatrix.h"
13 #include "readphylip.h"
14 #include "readcolumn.h"
15 #include "readmatrix.hpp"
16 #include "inputdata.h"
18 //**********************************************************************************************************************
19 //This function checks to make sure the cluster command has no errors and then clusters based on the method chosen.
20 ClusterSplitCommand::ClusterSplitCommand(string option) {
22 globaldata = GlobalData::getInstance();
26 //allow user to run help
27 if(option == "help") { help(); abort = true; }
30 //valid paramters for this command
31 string Array[] = {"fasta","phylip","column","name","cutoff","precision","method","splitmethod","taxonomy","taxlevel","large","showabund","timing","hard","processors","outputdir","inputdir"};
32 vector<string> myArray (Array, Array+(sizeof(Array)/sizeof(string)));
34 OptionParser parser(option);
35 map<string,string> parameters = parser.getParameters();
37 ValidParameters validParameter;
39 //check to make sure all parameters are valid for command
40 map<string,string>::iterator it;
41 for (it = parameters.begin(); it != parameters.end(); it++) {
42 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {
47 globaldata->newRead();
49 //if the user changes the output directory command factory will send this info to us in the output parameter
50 outputDir = validParameter.validFile(parameters, "outputdir", false); if (outputDir == "not found"){ outputDir = ""; }
52 //if the user changes the input directory command factory will send this info to us in the output parameter
53 string inputDir = validParameter.validFile(parameters, "inputdir", false);
54 if (inputDir == "not found"){ inputDir = ""; }
57 it = parameters.find("phylip");
58 //user has given a template file
59 if(it != parameters.end()){
60 path = hasPath(it->second);
61 //if the user has not given a path then, add inputdir. else leave path alone.
62 if (path == "") { parameters["phylip"] = inputDir + it->second; }
65 it = parameters.find("column");
66 //user has given a template file
67 if(it != parameters.end()){
68 path = hasPath(it->second);
69 //if the user has not given a path then, add inputdir. else leave path alone.
70 if (path == "") { parameters["column"] = inputDir + it->second; }
73 it = parameters.find("name");
74 //user has given a template file
75 if(it != parameters.end()){
76 path = hasPath(it->second);
77 //if the user has not given a path then, add inputdir. else leave path alone.
78 if (path == "") { parameters["name"] = inputDir + it->second; }
81 it = parameters.find("taxonomy");
82 //user has given a template file
83 if(it != parameters.end()){
84 path = hasPath(it->second);
85 //if the user has not given a path then, add inputdir. else leave path alone.
86 if (path == "") { parameters["taxonomy"] = inputDir + it->second; }
89 it = parameters.find("fasta");
90 //user has given a template file
91 if(it != parameters.end()){
92 path = hasPath(it->second);
93 //if the user has not given a path then, add inputdir. else leave path alone.
94 if (path == "") { parameters["fasta"] = inputDir + it->second; }
98 //check for required parameters
99 phylipfile = validParameter.validFile(parameters, "phylip", true);
100 if (phylipfile == "not open") { abort = true; }
101 else if (phylipfile == "not found") { phylipfile = ""; }
102 else { distfile = phylipfile; format = "phylip"; }
104 columnfile = validParameter.validFile(parameters, "column", true);
105 if (columnfile == "not open") { abort = true; }
106 else if (columnfile == "not found") { columnfile = ""; }
107 else { distfile = columnfile; format = "column"; }
109 namefile = validParameter.validFile(parameters, "name", true);
110 if (namefile == "not open") { abort = true; }
111 else if (namefile == "not found") { namefile = ""; }
113 fastafile = validParameter.validFile(parameters, "fasta", true);
114 if (fastafile == "not open") { abort = true; }
115 else if (fastafile == "not found") { fastafile = ""; }
116 else { splitmethod = "fasta"; }
118 taxFile = validParameter.validFile(parameters, "taxonomy", true);
119 if (taxFile == "not open") { abort = true; }
120 else if (taxFile == "not found") { taxFile = ""; }
122 if ((phylipfile == "") && (columnfile == "") && (fastafile == "")) { m->mothurOut("When executing a cluster.split command you must enter a phylip or a column or fastafile."); m->mothurOutEndLine(); abort = true; }
123 else if ((phylipfile != "") && (columnfile != "") && (fastafile != "")) { m->mothurOut("When executing a cluster.split command you must enter ONLY ONE of the following: fasta, phylip or column."); m->mothurOutEndLine(); abort = true; }
125 if (columnfile != "") {
126 if (namefile == "") { m->mothurOut("You need to provide a namefile if you are going to use the column format."); m->mothurOutEndLine(); abort = true; }
129 if (fastafile != "") {
130 if (taxFile == "") { m->mothurOut("You need to provide a taxonomy file if you are using a fasta file to generate the split."); m->mothurOutEndLine(); abort = true; }
133 //check for optional parameter and set defaults
134 // ...at some point should added some additional type checking...
135 //get user cutoff and precision or use defaults
137 temp = validParameter.validFile(parameters, "precision", false);
138 if (temp == "not found") { temp = "100"; }
139 //saves precision legnth for formatting below
140 length = temp.length();
141 convert(temp, precision);
143 temp = validParameter.validFile(parameters, "hard", false); if (temp == "not found") { temp = "F"; }
146 temp = validParameter.validFile(parameters, "large", false); if (temp == "not found") { temp = "F"; }
147 large = isTrue(temp);
149 temp = validParameter.validFile(parameters, "processors", false); if (temp == "not found"){ temp = "1"; }
150 convert(temp, processors);
152 temp = validParameter.validFile(parameters, "splitmethod", false);
153 if (splitmethod != "fasta") {
154 if (temp == "not found") { splitmethod = "distance"; }
155 else { splitmethod = temp; }
158 temp = validParameter.validFile(parameters, "cutoff", false); if (temp == "not found") { temp = "10"; }
159 convert(temp, cutoff);
160 cutoff += (5 / (precision * 10.0));
162 temp = validParameter.validFile(parameters, "taxlevel", false); if (temp == "not found") { temp = "1"; }
163 convert(temp, taxLevelCutoff);
165 method = validParameter.validFile(parameters, "method", false); if (method == "not found") { method = "furthest"; }
167 if ((method == "furthest") || (method == "nearest") || (method == "average")) { }
168 else { m->mothurOut("Not a valid clustering method. Valid clustering algorithms are furthest, nearest or average."); m->mothurOutEndLine(); abort = true; }
170 if ((splitmethod == "distance") || (splitmethod == "classify") || (splitmethod == "fasta")) { }
171 else { m->mothurOut(splitmethod + " is not a valid splitting method. Valid splitting algorithms are distance, classify or fasta."); m->mothurOutEndLine(); abort = true; }
173 if ((splitmethod == "classify") && (taxFile == "")) { m->mothurOut("You need to provide a taxonomy file if you are going to use the classify splitmethod."); m->mothurOutEndLine(); abort = true; }
175 showabund = validParameter.validFile(parameters, "showabund", false);
176 if (showabund == "not found") { showabund = "T"; }
178 timing = validParameter.validFile(parameters, "timing", false);
179 if (timing == "not found") { timing = "F"; }
183 catch(exception& e) {
184 m->errorOut(e, "ClusterSplitCommand", "ClusterSplitCommand");
189 //**********************************************************************************************************************
191 void ClusterSplitCommand::help(){
193 m->mothurOut("The cluster.split command parameter options are fasta, phylip, column, name, cutoff, precision, method, splitmethod, taxonomy, taxlevel, showabund, timing, hard, large, processors. Fasta or Phylip or column and name are required.\n");
194 m->mothurOut("The cluster.split command can split your files in 3 ways. Splitting by distance file, by classification, or by classification also using a fasta file. \n");
195 m->mothurOut("For the distance file method, you need only provide your distance file and mothur will split the file into distinct groups. \n");
196 m->mothurOut("For the classification method, you need to provide your distance file and taxonomy file, and set the splitmethod to classify. \n");
197 m->mothurOut("You will also need to set the taxlevel you want to split by. mothur will split the sequence into distinct taxonomy groups, and split the distance file based on those groups. \n");
198 m->mothurOut("For the classification method using a fasta file, you need to provide your fasta file and taxonomy file. \n");
199 m->mothurOut("You will also need to set the taxlevel you want to split by. mothur will split the sequence into distinct taxonomy groups, and create distance files for each grouping. \n");
200 m->mothurOut("The phylip and column parameter allow you to enter your distance file. \n");
201 m->mothurOut("The fasta parameter allows you to enter your aligned fasta file. \n");
202 m->mothurOut("The name parameter allows you to enter your name file and is required if your distance file is in column format. \n");
203 m->mothurOut("The cutoff parameter allow you to set the distance you want to cluster to, default is 10.0. \n");
204 m->mothurOut("The precision parameter allows you specify the precision of the precision of the distances outputted, default=100, meaning 2 decimal places. \n");
205 m->mothurOut("The method allows you to specify what clustering algorythm you want to use, default=furthest, option furthest, nearest, or average. \n");
206 m->mothurOut("The splitmethod parameter allows you to specify how you want to split your distance file before you cluster, default=distance, options distance, classify or fasta. \n");
207 m->mothurOut("The taxonomy parameter allows you to enter the taxonomy file for your sequences, this is only valid if you are using splitmethod=classify. Be sure your taxonomy file does not include the probability scores. \n");
208 m->mothurOut("The taxlevel parameter allows you to specify the taxonomy level you want to use to split the distance file, default=1. \n");
209 m->mothurOut("The large parameter allows you to indicate that your distance matrix is too large to fit in RAM. The default value is false.\n");
210 m->mothurOut("The cluster.split command should be in the following format: \n");
211 m->mothurOut("cluster.split(column=youDistanceFile, name=yourNameFile, method=yourMethod, cutoff=yourCutoff, precision=yourPrecision, splitmethod=yourSplitmethod, taxonomy=yourTaxonomyfile, taxlevel=yourtaxlevel) \n");
212 m->mothurOut("Example: cluster.split(column=abrecovery.dist, name=abrecovery.names, method=furthest, cutoff=0.10, precision=1000, splitmethod=classify, taxonomy=abrecovery.silva.slv.taxonomy, taxlevel=5) \n");
215 catch(exception& e) {
216 m->errorOut(e, "ClusterSplitCommand", "help");
221 //**********************************************************************************************************************
223 ClusterSplitCommand::~ClusterSplitCommand(){}
225 //**********************************************************************************************************************
227 int ClusterSplitCommand::execute(){
230 if (abort == true) { return 0; }
232 //****************** file prep work ******************************//
234 //if user gave a phylip file convert to column file
235 if (format == "phylip") {
237 m->mothurOut("Converting to column format..."); m->mothurOutEndLine();
239 ReadCluster* convert = new ReadCluster(distfile, cutoff, outputDir, false);
241 NameAssignment* nameMap = NULL;
242 convert->setFormat("phylip");
243 convert->read(nameMap);
245 if (m->control_pressed) { delete convert; return 0; }
247 distfile = convert->getOutputFile();
249 //if no names file given with phylip file, create it
250 ListVector* listToMakeNameFile = convert->getListVector();
251 if (namefile == "") { //you need to make a namefile for split matrix
253 namefile = phylipfile + ".names";
254 openOutputFile(namefile, out);
255 for (int i = 0; i < listToMakeNameFile->getNumBins(); i++) {
256 string bin = listToMakeNameFile->get(i);
257 out << bin << '\t' << bin << endl;
261 delete listToMakeNameFile;
264 m->mothurOut("It took " + toString(time(NULL) - estart) + " seconds to convert the distance file."); m->mothurOutEndLine();
266 if (m->control_pressed) { return 0; }
269 m->mothurOut("Splitting the file..."); m->mothurOutEndLine();
271 //split matrix into non-overlapping groups
273 if (splitmethod == "distance") { split = new SplitMatrix(distfile, namefile, taxFile, cutoff, splitmethod, large); }
274 else if (splitmethod == "classify") { split = new SplitMatrix(distfile, namefile, taxFile, taxLevelCutoff, splitmethod, large); }
275 else if (splitmethod == "fasta") { split = new SplitMatrix(fastafile, taxFile, taxLevelCutoff, splitmethod); }
276 else { m->mothurOut("Not a valid splitting method. Valid splitting algorithms are distance, classify or fasta."); m->mothurOutEndLine(); return 0; }
280 if (m->control_pressed) { delete split; return 0; }
282 string singletonName = split->getSingletonNames();
283 vector< map<string, string> > distName = split->getDistanceFiles(); //returns map of distance files -> namefile sorted by distance file size
286 if (m->control_pressed) { return 0; }
288 m->mothurOut("It took " + toString(time(NULL) - estart) + " seconds to split the distance file."); m->mothurOutEndLine();
291 //****************** break up files between processes and cluster each file set ******************************//
292 vector<string> listFileNames;
294 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
296 listFileNames = cluster(distName, labels); //clusters individual files and returns names of list files
298 vector < vector < map<string, string> > > dividedNames; //distNames[1] = vector of filenames for process 1...
299 dividedNames.resize(processors);
301 //for each file group figure out which process will complete it
302 //want to divide the load intelligently so the big files are spread between processes
304 for (int i = 0; i < distName.size(); i++) {
305 int processToAssign = (i+1) % processors;
306 if (processToAssign == 0) { processToAssign = processors; }
308 dividedNames[(processToAssign-1)].push_back(distName[i]);
311 //not lets reverse the order of ever other process, so we balance big files running with little ones
312 for (int i = 0; i < processors; i++) {
313 int remainder = ((i+1) % processors);
314 if (remainder) { reverse(dividedNames[i].begin(), dividedNames[i].end()); }
317 createProcesses(dividedNames);
319 if (m->control_pressed) { return 0; }
321 //get list of list file names from each process
322 for(int i=0;i<processors;i++){
323 string filename = toString(processIDS[i]) + ".temp";
325 openInputFile(filename, in);
327 in >> tag; gobble(in);
331 in >> tempName; gobble(in);
332 listFileNames.push_back(tempName);
335 remove((toString(processIDS[i]) + ".temp").c_str());
338 filename = toString(processIDS[i]) + ".temp.labels";
340 openInputFile(filename, in2);
344 in2 >> tempName; gobble(in2);
345 if (labels.count(tempName) == 0) { labels.insert(tempName); }
348 remove((toString(processIDS[i]) + ".temp.labels").c_str());
352 listFileNames = cluster(distName, labels); //clusters individual files and returns names of list files
355 if (m->control_pressed) { for (int i = 0; i < listFileNames.size(); i++) { remove(listFileNames[i].c_str()); } return 0; }
357 m->mothurOut("It took " + toString(time(NULL) - estart) + " seconds to cluster"); m->mothurOutEndLine();
359 //****************** merge list file and create rabund and sabund files ******************************//
361 m->mothurOut("Merging the clustered files..."); m->mothurOutEndLine();
363 ListVector* listSingle;
364 map<float, int> labelBins = completeListFile(listFileNames, singletonName, labels, listSingle); //returns map of label to numBins
366 if (m->control_pressed) { if (listSingle != NULL) { delete listSingle; } for (int i = 0; i < outputNames.size(); i++) { remove(outputNames[i].c_str()); } return 0; }
368 mergeLists(listFileNames, labelBins, listSingle);
370 if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) { remove(outputNames[i].c_str()); } return 0; }
372 m->mothurOut("It took " + toString(time(NULL) - estart) + " seconds to merge."); m->mothurOutEndLine();
374 m->mothurOutEndLine();
375 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
376 for (int i = 0; i < outputNames.size(); i++) { m->mothurOut(outputNames[i]); m->mothurOutEndLine(); }
377 m->mothurOutEndLine();
381 catch(exception& e) {
382 m->errorOut(e, "ClusterSplitCommand", "execute");
386 //**********************************************************************************************************************
387 map<float, int> ClusterSplitCommand::completeListFile(vector<string> listNames, string singleton, set<string>& userLabels, ListVector*& listSingle){
390 map<float, int> labelBin;
391 vector<float> orderFloat;
395 if (singleton != "none") {
397 openInputFile(singleton, in);
399 string firstCol, secondCol;
400 listSingle = new ListVector();
402 in >> firstCol >> secondCol; gobble(in);
403 listSingle->push_back(secondCol);
406 remove(singleton.c_str());
408 numSingleBins = listSingle->getNumBins();
409 }else{ listSingle = NULL; numSingleBins = 0; }
411 //go through users set and make them floats so we can sort them
412 for(set<string>::iterator it = userLabels.begin(); it != userLabels.end(); ++it) {
415 if ((*it != "unique") && (convertTestFloat(*it, temp) == true)) { convert(*it, temp); }
416 else if (*it == "unique") { temp = -1.0; }
418 orderFloat.push_back(temp);
419 labelBin[temp] = numSingleBins; //initialize numbins
423 sort(orderFloat.begin(), orderFloat.end());
426 //get the list info from each file
427 for (int k = 0; k < listNames.size(); k++) {
429 if (m->control_pressed) {
430 if (listSingle != NULL) { delete listSingle; listSingle = NULL; remove(singleton.c_str()); }
431 for (int i = 0; i < listNames.size(); i++) { remove(listNames[i].c_str()); }
435 InputData* input = new InputData(listNames[k], "list");
436 ListVector* list = input->getListVector();
437 string lastLabel = list->getLabel();
439 string filledInList = listNames[k] + "filledInTemp";
441 openOutputFile(filledInList, outFilled);
443 //for each label needed
444 for(int l = 0; l < orderFloat.size(); l++){
447 if (orderFloat[l] == -1) { thisLabel = "unique"; }
448 else { thisLabel = toString(orderFloat[l], length-1); }
450 //this file has reached the end
452 list = input->getListVector(lastLabel, true);
453 }else{ //do you have the distance, or do you need to fill in
456 if (list->getLabel() == "unique") { labelFloat = -1.0; }
457 else { convert(list->getLabel(), labelFloat); }
459 //check for missing labels
460 if (labelFloat > orderFloat[l]) { //you are missing the label, get the next smallest one
461 //if its bigger get last label, otherwise keep it
463 list = input->getListVector(lastLabel, true); //get last list vector to use, you actually want to move back in the file
465 lastLabel = list->getLabel();
469 list->setLabel(thisLabel);
470 list->print(outFilled);
473 labelBin[orderFloat[l]] += list->getNumBins();
477 list = input->getListVector();
480 if (list != NULL) { delete list; }
484 remove(listNames[k].c_str());
485 rename(filledInList.c_str(), listNames[k].c_str());
490 catch(exception& e) {
491 m->errorOut(e, "ClusterSplitCommand", "completeListFile");
495 //**********************************************************************************************************************
496 int ClusterSplitCommand::mergeLists(vector<string> listNames, map<float, int> userLabels, ListVector* listSingle){
498 if (outputDir == "") { outputDir += hasPath(distfile); }
499 fileroot = outputDir + getRootName(getSimpleName(distfile));
501 openOutputFile(fileroot+ tag + ".sabund", outSabund);
502 openOutputFile(fileroot+ tag + ".rabund", outRabund);
503 openOutputFile(fileroot+ tag + ".list", outList);
505 outputNames.push_back(fileroot+ tag + ".sabund");
506 outputNames.push_back(fileroot+ tag + ".rabund");
507 outputNames.push_back(fileroot+ tag + ".list");
509 map<float, int>::iterator itLabel;
511 //for each label needed
512 for(itLabel = userLabels.begin(); itLabel != userLabels.end(); itLabel++) {
515 if (itLabel->first == -1) { thisLabel = "unique"; }
516 else { thisLabel = toString(itLabel->first, length-1); }
518 outList << thisLabel << '\t' << itLabel->second << '\t';
520 RAbundVector* rabund = new RAbundVector();
521 rabund->setLabel(thisLabel);
524 if (listSingle != NULL) {
525 for (int j = 0; j < listSingle->getNumBins(); j++) {
526 outList << listSingle->get(j) << '\t';
527 rabund->push_back(getNumNames(listSingle->get(j)));
531 //get the list info from each file
532 for (int k = 0; k < listNames.size(); k++) {
534 if (m->control_pressed) { if (listSingle != NULL) { delete listSingle; } for (int i = 0; i < listNames.size(); i++) { remove(listNames[i].c_str()); } delete rabund; return 0; }
536 InputData* input = new InputData(listNames[k], "list");
537 ListVector* list = input->getListVector(thisLabel);
539 //this file has reached the end
540 if (list == NULL) { m->mothurOut("Error merging listvectors in file " + listNames[k]); m->mothurOutEndLine(); }
542 for (int j = 0; j < list->getNumBins(); j++) {
543 outList << list->get(j) << '\t';
544 rabund->push_back(getNumNames(list->get(j)));
551 SAbundVector sabund = rabund->getSAbundVector();
553 sabund.print(outSabund);
554 rabund->print(outRabund);
564 if (listSingle != NULL) { delete listSingle; }
566 for (int i = 0; i < listNames.size(); i++) { remove(listNames[i].c_str()); }
570 catch(exception& e) {
571 m->errorOut(e, "ClusterSplitCommand", "mergeLists");
576 //**********************************************************************************************************************
578 void ClusterSplitCommand::printData(ListVector* oldList){
580 string label = oldList->getLabel();
581 RAbundVector oldRAbund = oldList->getRAbundVector();
583 oldRAbund.setLabel(label);
584 if (isTrue(showabund)) {
585 oldRAbund.getSAbundVector().print(cout);
587 oldRAbund.print(outRabund);
588 oldRAbund.getSAbundVector().print(outSabund);
590 oldList->print(outList);
592 catch(exception& e) {
593 m->errorOut(e, "ClusterSplitCommand", "printData");
597 //**********************************************************************************************************************
598 int ClusterSplitCommand::createProcesses(vector < vector < map<string, string> > > dividedNames){
601 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
606 //loop through and create all the processes you want
607 while (process != processors) {
611 processIDS.push_back(pid); //create map from line number to pid so you can append files in correct order later
615 vector<string> listFileNames = cluster(dividedNames[process], labels);
617 //write out names to file
618 string filename = toString(getpid()) + ".temp";
620 openOutputFile(filename, out);
622 for (int j = 0; j < listFileNames.size(); j++) { out << listFileNames[j] << endl; }
627 filename = toString(getpid()) + ".temp.labels";
628 openOutputFile(filename, outLabels);
630 for (set<string>::iterator it = labels.begin(); it != labels.end(); it++) {
631 outLabels << (*it) << endl;
636 }else { m->mothurOut("unable to spawn the necessary processes."); m->mothurOutEndLine(); exit(0); }
639 //force parent to wait until all the processes are done
640 for (int i=0;i<processors;i++) {
641 int temp = processIDS[i];
649 catch(exception& e) {
650 m->errorOut(e, "ClusterSplitCommand", "createProcesses");
654 //**********************************************************************************************************************
656 vector<string> ClusterSplitCommand::cluster(vector< map<string, string> > distNames, set<string>& labels){
659 SparseMatrix* matrix;
662 RAbundVector* rabund;
664 vector<string> listFileNames;
666 //cluster each distance file
667 for (int i = 0; i < distNames.size(); i++) {
669 string thisNamefile = distNames[i].begin()->second;
670 string thisDistFile = distNames[i].begin()->first;
672 //read in distance file
673 globaldata->setNameFile(thisNamefile);
674 globaldata->setColumnFile(thisDistFile); globaldata->setFormat("column");
676 m->mothurOutEndLine(); m->mothurOut("Reading " + thisDistFile); m->mothurOutEndLine();
678 ReadMatrix* read = new ReadColumnMatrix(thisDistFile);
679 read->setCutoff(cutoff);
681 NameAssignment* nameMap = new NameAssignment(thisNamefile);
685 if (m->control_pressed) { delete read; delete nameMap; return listFileNames; }
687 list = read->getListVector();
689 matrix = read->getMatrix();
694 m->mothurOutEndLine(); m->mothurOut("Clustering " + thisDistFile); m->mothurOutEndLine();
696 rabund = new RAbundVector(list->getRAbundVector());
699 if (method == "furthest") { cluster = new CompleteLinkage(rabund, list, matrix, cutoff, method); }
700 else if(method == "nearest"){ cluster = new SingleLinkage(rabund, list, matrix, cutoff, method); }
701 else if(method == "average"){ cluster = new AverageLinkage(rabund, list, matrix, cutoff, method); }
702 tag = cluster->getTag();
704 if (outputDir == "") { outputDir += hasPath(thisDistFile); }
705 fileroot = outputDir + getRootName(getSimpleName(thisDistFile));
708 openOutputFile(fileroot+ tag + ".list", listFile);
710 listFileNames.push_back(fileroot+ tag + ".list");
712 time_t estart = time(NULL);
714 float previousDist = 0.00000;
715 float rndPreviousDist = 0.00000;
721 double saveCutoff = cutoff;
723 while (matrix->getSmallDist() < cutoff && matrix->getNNodes() > 0){
725 if (m->control_pressed) { //clean up
726 delete matrix; delete list; delete cluster; delete rabund;
728 for (int i = 0; i < listFileNames.size(); i++) { remove(listFileNames[i].c_str()); }
729 listFileNames.clear(); return listFileNames;
732 cluster->update(cutoff);
734 float dist = matrix->getSmallDist();
737 rndDist = ceilDist(dist, precision);
739 rndDist = roundDist(dist, precision);
742 if(previousDist <= 0.0000 && dist != previousDist){
743 oldList.setLabel("unique");
744 oldList.print(listFile);
745 if (labels.count("unique") == 0) { labels.insert("unique"); }
747 else if(rndDist != rndPreviousDist){
748 oldList.setLabel(toString(rndPreviousDist, length-1));
749 oldList.print(listFile);
750 if (labels.count(toString(rndPreviousDist, length-1)) == 0) { labels.insert(toString(rndPreviousDist, length-1)); }
754 rndPreviousDist = rndDist;
759 if(previousDist <= 0.0000){
760 oldList.setLabel("unique");
761 oldList.print(listFile);
762 if (labels.count("unique") == 0) { labels.insert("unique"); }
764 else if(rndPreviousDist<cutoff){
765 oldList.setLabel(toString(rndPreviousDist, length-1));
766 oldList.print(listFile);
767 if (labels.count(toString(rndPreviousDist, length-1)) == 0) { labels.insert(toString(rndPreviousDist, length-1)); }
770 delete matrix; delete list; delete cluster; delete rabund;
773 if (m->control_pressed) { //clean up
774 for (int i = 0; i < listFileNames.size(); i++) { remove(listFileNames[i].c_str()); }
775 listFileNames.clear(); return listFileNames;
778 //remove(thisDistFile.c_str());
779 //remove(thisNamefile.c_str());
783 return listFileNames;
786 catch(exception& e) {
787 m->errorOut(e, "ClusterSplitCommand", "cluster");
794 //**********************************************************************************************************************