[med-svn] [Git][med-team/mothur][upstream] New upstream version 1.48.1
Tomasz Buchert (@tomasz)
gitlab at salsa.debian.org
Sun Jun 2 09:35:12 BST 2024
Tomasz Buchert pushed to branch upstream at Debian Med / mothur
Commits:
610156ad by Tomasz Buchert at 2024-06-02T10:15:44+02:00
New upstream version 1.48.1
- - - - -
27 changed files:
- Makefile
- Mothur.xcodeproj/project.pbxproj
- source/commands/countseqscommand.cpp
- source/commands/fastaqinfocommand.cpp
- source/commands/fastaqinfocommand.h
- source/commands/getmimarkspackagecommand.cpp
- source/commands/getoturepcommand.cpp
- source/commands/makecontigscommand.cpp
- source/commands/makecontigscommand.h
- source/commands/makefilecommand.cpp
- source/commands/makefilecommand.h
- source/commands/makegroupcommand.cpp
- source/commands/makegroupcommand.h
- source/commands/pcrseqscommand.cpp
- source/commands/preclustercommand.cpp
- source/commands/removelineagecommand.cpp
- source/commands/renameseqscommand.cpp
- source/commands/renameseqscommand.h
- source/commands/setcurrentcommand.cpp
- source/commands/sracommand.cpp
- source/commands/subsamplecommand.cpp
- source/datastructures/filefile.cpp
- source/datastructures/filefile.hpp
- source/datastructures/oligos.cpp
- source/datastructures/oligos.h
- source/datastructures/sequence.cpp
- source/validparameter.cpp
Changes:
=====================================
Makefile
=====================================
@@ -37,8 +37,8 @@ GSL_LIBRARY_DIR ?= "\"Enter_your_GSL_library_path_here\""
GSL_INCLUDE_DIR ?= "\"Enter_your_GSL_include_path_here\""
MOTHUR_FILES="\"Enter_your_default_path_here\""
MOTHUR_TOOLS="\"Enter_your_mothur_tools_path_here\""
-VERSION = "\"1.48.0\""
-RELEASE_DATE = "\"5/20/22\""
+VERSION = "\"1.48.1\""
+RELEASE_DATE = "\"5/15/24\""
# Set a static logfile name
=====================================
Mothur.xcodeproj/project.pbxproj
=====================================
@@ -3982,11 +3982,11 @@
GCC_C_LANGUAGE_STANDARD = "compiler-default";
GCC_DYNAMIC_NO_PIC = NO;
GCC_MODEL_TUNING = G5;
- GCC_OPTIMIZATION_LEVEL = 3;
+ GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
- "MOTHUR_FILES=\"\\\"/Users/swestcott/Desktop/release/;/Users/swestcott/Desktop/mothurbugs/\\\"\"",
+ "MOTHUR_FILES=\"\\\"/Users/swestcott/Desktop/MothurStuff/release/;/Users/swestcott/Desktop/MothurStuff/mothurbugs/\\\"\"",
"VERSION=\"\\\"1.48.0\\\"\"",
- "MOTHUR_TOOLS=\"\\\"/Users/swestcott/Desktop/mothur/tools/;/Users/swestcott/Desktop/release/\\\"\"",
+ "MOTHUR_TOOLS=\"\\\"/Users/swestcott/Desktop/MothurStuff/mothur/tools/;/Users/swestcott/Desktop/release/\\\"\"",
"LOGFILE_NAME=\"\\\"./mothur.logfile\\\"\"",
);
GCC_VERSION = "";
@@ -4034,12 +4034,12 @@
"FRAMEWORK_SEARCH_PATHS[arch=*]" = "${SRCROOT}/mothur_resources_10.14/libs";
GCC_C_LANGUAGE_STANDARD = "compiler-default";
GCC_MODEL_TUNING = G5;
- GCC_OPTIMIZATION_LEVEL = 3;
+ GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
- "MOTHUR_FILES=\"\\\"/Users/swestcott/Desktop/release\\\"\"",
+ "MOTHUR_FILES=\"\\\"/Users/swestcott/Desktop/MothurStuff/release\\\"\"",
"VERSION=\"\\\"1.48.0\\\"\"",
"LOGFILE_NAME=\"\\\"./mothur.logfile\\\"\"",
- "MOTHUR_TOOLS=\"\\\"/Users/swestcott/desktop/mothur/tools/\\\"\"",
+ "MOTHUR_TOOLS=\"\\\"/Users/swestcott/desktop/MothurStuff/mothur/tools/\\\"\"",
);
GCC_VERSION = "";
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
@@ -4105,7 +4105,7 @@
GCC_ENABLE_SSE41_EXTENSIONS = NO;
GCC_ENABLE_SSE42_EXTENSIONS = NO;
GCC_NO_COMMON_BLOCKS = YES;
- GCC_OPTIMIZATION_LEVEL = 3;
+ GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"MOTHUR_FILES=\"\\\"/Users/swestcott/Desktop/release\\\"\"",
"VERSION=\"\\\"1.47.0\\\"\"",
@@ -4196,7 +4196,7 @@
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_MODEL_TUNING = "";
GCC_NO_COMMON_BLOCKS = YES;
- GCC_OPTIMIZATION_LEVEL = 3;
+ GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"VERSION=\"\\\"1.47.0\\\"\"",
"MOTHUR_FILES=\"\\\"/Users/swestcott/Desktop/release\\\"\"",
=====================================
source/commands/countseqscommand.cpp
=====================================
@@ -124,9 +124,6 @@ CountSeqsCommand::CountSeqsCommand(string option) : Command() {
string temp = validParameter.valid(parameters, "compress"); if (temp == "not found") { temp = "t"; }
compress = util.isTrue(temp);
-
-
-
}
}
@@ -263,7 +260,7 @@ unsigned long long CountSeqsCommand::process(string outputFileName){
if (compress) {
ct.printCompressedTable(outputFileName);
}else {
- ct.printTable(outputFileName);
+ ct.printTable(outputFileName, false);
}
outputNames.push_back(outputFileName); outputTypes["count"].push_back(outputFileName);
=====================================
source/commands/fastaqinfocommand.cpp
=====================================
@@ -201,7 +201,9 @@ int ParseFastaQCommand::execute(){
else { trimOligos = new TrimOligos(pdiffs, bdiffs, ldiffs, sdiffs, oligos.getPrimers(), oligos.getBarcodes(), oligos.getReversePrimers(), oligos.getLinkers(), oligos.getSpacers()); numPrimers = oligos.getPrimers().size(); numBarcodes = oligos.getBarcodes().size(); }
if (reorient) {
- rtrimOligos = new TrimOligos(pdiffs, bdiffs, 0, 0, oligos.getReorientedPairedPrimers(), oligos.getReorientedPairedBarcodes(), hasIndex); numBarcodes = oligos.getReorientedPairedBarcodes().size();
+ rtrimOligos = new TrimOligos(pdiffs, bdiffs, 0, 0, oligos.getReorientedPairedPrimers(), oligos.getReorientedPairedBarcodes(), hasIndex);
+ numBarcodes = oligos.getReorientedPairedBarcodes().size();
+ numPrimers = oligos.getReorientedPairedPrimers().size();
}
}else if (groupfile != "") { readGroup(groupfile); }
@@ -742,7 +744,7 @@ set<string> ParseFastaQCommand::processFile(string inputfile, TrimOligos*& trimO
seqGroups[copy.getName()] = thisGroup;
map<string, long long>::iterator it = groupCounts.find(thisGroup);
- if (it == groupCounts.end()) { groupCounts[thisGroup] = 1; }
+ if (it == groupCounts.end()) { groupCounts[thisGroup] = 1; }
else { groupCounts[it->first]++; }
}
}else { addToScrap = true; }
@@ -818,6 +820,7 @@ int ParseFastaQCommand::findGroup(Sequence& currSeq, QualityScores& currQual, st
else { success = results[0]; }
if(success > bdiffs) { trashCode += 'b'; }
else{ currentSeqsDiffs += success; }
+
}
if(numSpacers != 0){
@@ -1028,7 +1031,7 @@ vector< vector<string> > ParseFastaQCommand::readFile(){
FileFile dataFile(inputfile, mode);
vector< vector<string> > files = dataFile.getFiles(); //if pacbio 2 columns, files[x][0] = filename, files[x][1] = "", files[x][2] = "", files[x][3] = "",
- file2Group = dataFile.getFile2Group();
+ file2Group = dataFile.getGroupNames();
createFileGroup = dataFile.isColumnWithGroupNames();
hasIndex = dataFile.containsIndexFiles();
int dataFileFormat = dataFile.getFileFormat();
=====================================
source/commands/fastaqinfocommand.h
=====================================
@@ -48,7 +48,7 @@ private:
GroupMap* groupMap;
Oligos oligos;
- map<int, string> file2Group;
+ vector<string> file2Group;
vector< vector<string> > readFile();
string ffqnoMatchFile, rfqnoMatchFile, ffnoMatchFile, rfnoMatchFile, fqnoMatchFile, rqnoMatchFile;
vector<string> Groups;
=====================================
source/commands/getmimarkspackagecommand.cpp
=====================================
@@ -396,8 +396,8 @@ int GetMIMarksPackageCommand::readFile(){
if (fileOption == 2) { // 3 column file with group names
- map<int, string> fileIndex2GroupName = dataFile.getFile2Group();
- for (map<int, string>::iterator it = fileIndex2GroupName.begin(); it != fileIndex2GroupName.end(); it++) { Groups.insert(it->second); }
+ vector<string> groupNames = dataFile.getGroupNames();
+ for (auto name : groupNames) { Groups.insert(name); }
}else if (fileOption == 1) { //2 column format, extract names from oligos file
=====================================
source/commands/getoturepcommand.cpp
=====================================
@@ -334,8 +334,13 @@ int GetOTURepCommand::execute(){
if (method == "distance") { readDist(); }
- InputData input(listfile, "list", Groups);
- ListVector* list = input.getListVector(*it);
+ InputData input(listfile, "list", nullVector);
+ set<string> processedLabels;
+ set<string> userLabels; userLabels.insert(*it);
+ string lastLabel = "";
+
+ ListVector* list = util.getNextList(input, allLines, userLabels, processedLabels, lastLabel);
+
if (list != nullptr) {
string lastLabel = list->getLabel();
=====================================
source/commands/makecontigscommand.cpp
=====================================
@@ -167,7 +167,7 @@ string MakeContigsCommand::getHelpString(){
helpString += "The mistmatch parameter allows you to specify the penalty for having different bases. The default is -1.0.\n";
helpString += "The checkorient parameter will look for the reverse compliment of the barcode or primer in the sequence. If found the sequence is flipped. The default is true.\n";
helpString += "The deltaq parameter allows you to specify the delta allowed between quality scores of a mismatched base. For example in the overlap, if deltaq=5 and in the alignment seqA, pos 200 has a quality score of 30 and the same position in seqB has a quality score of 20, you take the base from seqA (30-20 >= 5). If the quality score in seqB is 28 then the base in the consensus will be an N (30-28<5). The default is 6.\n";
- helpString += "The maxee parameter allows you to specify the maximum number of errors to allow in a sequence. Makes sense to use with deltaq=0. This numbrer is a decimal number. The expected numbrer of errors is based on Edgar's approach used in USEARCH/VSEARCH.";
+ helpString += "The maxee parameter allows you to specify the maximum number of errors to allow in a sequence. Makes sense to use with deltaq=0. This number is a decimal number. The expected number of errors is based on Edgar's approach used in USEARCH/VSEARCH.";
helpString += "The gapopen parameter allows you to specify the penalty for opening a gap in an alignment. The default is -2.0.\n";
helpString += "The gapextend parameter allows you to specify the penalty for extending a gap in an alignment. The default is -1.0.\n";
helpString += "The insert parameter allows you to set a quality scores threshold. In the case where we are trying to decide whether to keep a base or remove it because the base is compared to a gap in the other fragment, if the base has a quality score equal to or below the threshold we eliminate it. Default=20.\n";
@@ -324,12 +324,10 @@ MakeContigsCommand::MakeContigsCommand(string option) : Command() {
temp = validParameter.valid(parameters, "pdiffs"); if (temp == "not found") { temp = "0"; }
util.mothurConvert(temp, pdiffs);
- sdiffs = 0;
-
temp = validParameter.valid(parameters, "tdiffs"); if (temp == "not found") { int tempTotal = pdiffs + bdiffs; temp = toString(tempTotal); }
util.mothurConvert(temp, tdiffs);
- if(tdiffs == 0){ tdiffs = bdiffs + pdiffs; } //+ ldiffs + sdiffs;
+ if(tdiffs == 0){ tdiffs = bdiffs + pdiffs; }
temp = validParameter.valid(parameters, "allfiles"); if (temp == "not found") { temp = "F"; }
allFiles = util.isTrue(temp);
@@ -829,12 +827,12 @@ struct groupContigsData {
int start, end;
vector< vector<string> > fileInputs;
set<string> badNames;
- map<int, string> file2Groups;
+ vector<string> file2Groups;
contigsData* bundle;
long long count;
groupContigsData() = default;
- groupContigsData(vector< vector<string> > fi, int s, int e, contigsData* cd, map<int, string> f2g) {
+ groupContigsData(vector< vector<string> > fi, int s, int e, contigsData* cd, vector<string> f2g) {
fileInputs = fi;
start = s;
end = e;
@@ -979,7 +977,7 @@ int setNameType(string forwardFile, string reverseFile, char delim, int& offByOn
unsigned long long MakeContigsCommand::processMultipleFileOption(string& compositeFastaFile, string& compositeMisMatchFile) {
try {
//read file
- map<int, string> file2Group;
+ vector<string> file2Group;
vector< vector<string> > fileInputs = readFileNames(file, file2Group); if (m->getControl_pressed()) { return 0; }
unsigned long long numReads = 0;
@@ -2191,7 +2189,7 @@ void driverContigsGroups(groupContigsData* gparams) {
}
//**********************************************************************************************************************
//only getting here is gz=true
-unsigned long long MakeContigsCommand::createProcessesGroups(vector< vector<string> > fileInputs, string compositeFastaFile, string compositeScrapFastaFile, string compositeQualFile, string compositeScrapQualFile, string compositeMisMatchFile, map<int, string>& file2Groups) {
+unsigned long long MakeContigsCommand::createProcessesGroups(vector< vector<string> > fileInputs, string compositeFastaFile, string compositeScrapFastaFile, string compositeQualFile, string compositeScrapQualFile, string compositeMisMatchFile, vector<string>& file2Groups) {
try {
map<int, oligosPair> pairedPrimers, rpairedPrimers, revpairedPrimers, pairedBarcodes, rpairedBarcodes, revpairedBarcodes;
vector<string> barcodeNames, primerNames;
@@ -2641,13 +2639,13 @@ int MakeContigsCommand::setLines(vector<string> fasta, vector<string> qual, vect
// forward.fastq reverse.fastq forward.index.fastq reverse.index.fastq -> 4 column
// forward.fastq reverse.fastq none reverse.index.fastq -> 4 column
// forward.fastq reverse.fastq forward.index.fastq none -> 4 column
-vector< vector<string> > MakeContigsCommand::readFileNames(string filename, map<int, string>& file2Group){
+vector< vector<string> > MakeContigsCommand::readFileNames(string filename, vector<string>& file2Group){
try {
FileFile dataFile(filename, "contigs");
vector< vector<string> > files = dataFile.getFiles();
gz = dataFile.isGZ();
- file2Group = dataFile.getFile2Group();
+ file2Group = dataFile.getGroupNames();
createFileGroup = dataFile.isColumnWithGroupNames();
if (dataFile.containsIndexFiles() && (oligosfile == "")) { m->mothurOut("[ERROR]: You need to provide an oligos file if you are going to use an index file.\n"); m->setControl_pressed(true); }
=====================================
source/commands/makecontigscommand.h
=====================================
@@ -68,7 +68,7 @@ private:
bool abort, allFiles, trimOverlap, createFileGroup, createOligosGroup, makeCount, noneOk, reorient, gz, makeQualFile, screenSequences;
string ffastqfile, rfastqfile, align, oligosfile, rfastafile, ffastafile, rqualfile, fqualfile, findexfile, rindexfile, file, format, inputDir;
float match, misMatch, gapOpen, gapExtend, maxee;
- int processors, longestBase, insert, tdiffs, bdiffs, pdiffs, ldiffs, sdiffs, deltaq, kmerSize, nameType, offByOneTrimLength, maxAmbig, maxHomoP, maxLength;
+ int processors, longestBase, insert, tdiffs, bdiffs, pdiffs, deltaq, kmerSize, nameType, offByOneTrimLength, maxAmbig, maxHomoP, maxLength;
vector<string> outputNames;
set<string> badNames;
map<string, int> groupCounts;
@@ -78,10 +78,10 @@ private:
unsigned long long processSingleFileOption(string& outFastaFile, string& outScrapFastaFile, string& outQualFile, string& outScrapQualFile, string& outMisMatchFile, string group);
unsigned long long createProcesses(vector<string>, vector<string>, string, string, string, string, string, vector<vector<string> >, vector<vector<string> >, string, map<int, oligosPair>& pairedPrimers, map<int, oligosPair>& rpairedPrimers, map<int, oligosPair>&, map<int, oligosPair>& pairedBarcodes, map<int, oligosPair>& rpairedBarcodes,map<int, oligosPair>&, vector<string>& barcodeNames, vector<string>& primerNames);
- unsigned long long createProcessesGroups(vector< vector<string> >, string compositeFastaFile, string compositeScrapFastaFile, string compositeQualFile, string compositeScrapQualFile, string compositeMisMatchFile, map<int, string>& file2Groups);
+ unsigned long long createProcessesGroups(vector< vector<string> >, string compositeFastaFile, string compositeScrapFastaFile, string compositeQualFile, string compositeScrapQualFile, string compositeMisMatchFile, vector<string>& file2Groups);
int createCountFile(string outputGroupFile, string resultFastafile);
- vector< vector<string> > readFileNames(string, map<int, string>&);
+ vector< vector<string> > readFileNames(string, vector<string>&);
bool getOligos(map<int, oligosPair>& pairedPrimers, map<int, oligosPair>& rpairedPrimers, map<int, oligosPair>&, map<int, oligosPair>& pairedBarcodes, map<int, oligosPair>& rpairedBarcodes, map<int, oligosPair>&, vector<string>& barcodeNames, vector<string>& primerNames);
int setLines(vector<string>, vector<string>, vector<linePair>& fastaFilePos, vector<linePair>& qfileFilePos, char delim); //the delim let you know whether this is fasta and qual, or fastq and index. linePair entries will always be in sets of two. One for the forward and one for hte reverse. (fastaFilePos[0] - ffasta, fastaFilePos[1] - rfasta) - processor1
//bool testGZReadable(vector<string>&, vector<string>&, bool&);
=====================================
source/commands/makefilecommand.cpp
=====================================
@@ -11,7 +11,7 @@
//**********************************************************************************************************************
vector<string> MakeFileCommand::setParameters(){
try {
- CommandParameter ptype("type", "Multiple", "fastq-gz", "fastq", "", "", "","",false,false); parameters.push_back(ptype);
+ CommandParameter ptype("type", "Multiple", "fasta-fastq-gz", "fastq", "", "", "","",false,false); parameters.push_back(ptype);
CommandParameter pnumcols("numcols", "Multiple", "2-3", "3", "", "", "","",false,false, true); parameters.push_back(pnumcols);
CommandParameter pseed("seed", "Number", "", "0", "", "", "","",false,false); parameters.push_back(pseed);
CommandParameter pprefix("prefix", "String", "", "", "", "", "","",false,false); parameters.push_back(pprefix);
@@ -37,11 +37,11 @@ vector<string> MakeFileCommand::setParameters(){
string MakeFileCommand::getHelpString(){
try {
string helpString = "";
- helpString += "The make.file command takes a input directory and creates a file file containing the fastq or gz files in the directory.\n";
+ helpString += "The make.file command takes a input directory and creates a file file containing the fasta, fastq or gz files in the directory.\n";
helpString += "The make.file command parameters are inputdir, numcols, type and prefix. inputdir is required.\n";
helpString += "May create more than one file. Mothur will attempt to match paired files. \n";
- helpString += "The type parameter allows you to set the type of files to look for. Options are fastq or gz. Default=fastq. \n";
- helpString += "The numcols parameter allows you to set number of columns you mothur to make in the file. Default=3, meaning groupName forwardFastq reverseFastq. The groupName is made from the beginning part of the forwardFastq file. Everything up to the first '_' or if no '_' is found then the root of the forwardFastq filename.\n";
+ helpString += "The type parameter allows you to set the type of files to look for. Options are fasta, fastq or gz. Default=fastq. \n";
+ helpString += "The numcols parameter allows you to set number of columns you mothur to make in the file. Default=3 for fastq and gz, meaning groupName forwardFastq reverseFastq. The groupName is made from the beginning part of the forwardFastq file. Everything up to the first '_' or if no '_' is found then the root of the forwardFastq filename. Default=2 for fasta files, meaning groupName fastaFile.\n";
helpString += "The prefix parameter allows you to enter your own prefix for the output filename. Default=stability.";
helpString += "The delim parameter allow you to enter the character you would like to use to create the sample name. Default='_'. For example, M6D7_S163_L001_R2_001.fastq.gz would produce the sample name M6D7. Set delim=* to indicate you want mothur to create unique names for each file pair. (no pooling)\n";
helpString += "The make.file command should be in the following format: \n";
@@ -94,12 +94,12 @@ MakeFileCommand::MakeFileCommand(string option) : Command() {
typeFile = validParameter.valid(parameters, "type");
if (typeFile == "not found"){ typeFile = "fastq"; }
- if ((typeFile != "fastq") && (typeFile != "gz")) { m->mothurOut(typeFile + " is not a valid type. Options are fastq or gz. I will use fastq.\n"); typeFile = "fastq"; }
+ if ((typeFile != "fastq") && (typeFile != "gz") && (typeFile != "fasta")) { m->mothurOut(typeFile + " is not a valid type. Options are fasta, fastq or gz. I will use fastq.\n"); typeFile = "fastq"; }
- string temp = validParameter.valid(parameters, "numcols"); if(temp == "not found"){ temp = "3"; }
+ string temp = validParameter.valid(parameters, "numcols"); if(temp == "not found"){ temp = "3"; if (typeFile == "fasta") { temp = "2"; } }
if ((temp != "2") && (temp != "3")) { m->mothurOut(temp + " is not a valid numcols. Options are 2 or 3. I will use 3.\n"); temp = "3"; }
util.mothurConvert(temp, numCols);
-
+ cout << numCols << endl;
prefix = validParameter.valid(parameters, "prefix"); if (prefix == "not found") { prefix = "stability"; }
delim = validParameter.valid(parameters, "delim"); if (delim == "not found") { delim = "_"; }
@@ -122,221 +122,340 @@ int MakeFileCommand::execute(){
fillAccnosFile(tempFile);
//read in list of files
- vector<string> fastqFiles;
- util.readAccnos(tempFile, fastqFiles, "no error");
+ vector<string> files;
+ util.readAccnos(tempFile, files, "no error");
util.mothurRemove(tempFile);
if (m->getDebug()) {
- m->mothurOut("[DEBUG]: Found " + toString(fastqFiles.size()) + " files of type " + typeFile + ".\n");
- for (int i = 0; i < fastqFiles.size(); i++) { m->mothurOut("[DEBUG]: " + toString(i) + " = " + fastqFiles[i] + "\n");}
+ m->mothurOut("[DEBUG]: Found " + toString(files.size()) + " files of type " + typeFile + ".\n");
+ for (int i = 0; i < files.size(); i++) { m->mothurOut("[DEBUG]: " + toString(i) + " = " + files[i] + "\n");}
}
- if (fastqFiles.size() == 0) { m->mothurOut("[WARNING]: Unable to find any " + typeFile + " files in your directory.\n"); }
+ if (files.size() == 0) { m->mothurOut("[WARNING]: Unable to find any " + typeFile + " files in your directory.\n"); }
else {
//sort into alpha order to put pairs togther if they exist
- sort(fastqFiles.begin(), fastqFiles.end());
+ sort(files.begin(), files.end());
- vector< vector<string> > paired;
+ if (typeFile == "fasta") { createFastaFile(files); }
+ else { createFastqGzFile(files); }
+ }
+
+ if (m->getControl_pressed()) { for (int i = 0; i < outputNames.size(); i++) { util.mothurRemove(outputNames[i]); } return 0; }
+
+ m->mothurOut("\nOutput File Names: \n");
+ for (int i = 0; i < outputNames.size(); i++) { m->mothurOut(outputNames[i]+"\n"); }
+ m->mothurOutEndLine();
+
+ return 0;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "MakeFileCommand", "execute");
+ exit(1);
+ }
+}
+//**********************************************************************************************************************
+
+void MakeFileCommand::createFastaFile(vector<string> files){
+ try {
+ map<string, string> variables;
+ variables["[filename]"] = outputdir + prefix + ".";
+ string filename = getOutputFileName("file",variables);
+
+ ofstream out; util.openOutputFile(filename, out);
+ outputNames.push_back(filename); outputTypes["file"].push_back(filename);
+ current->setFileFile(filename);
+
+ vector< vector<string> > outputs;
+ if (numCols == 3) {
vector<string> singles;
- set<string> groups;
- string lastFile = "";
- for (int i = 0; i < fastqFiles.size()-1; i++) {
-
- if (m->getDebug()) { m->mothurOut("[DEBUG]: File " + toString(i) + " = " + fastqFiles[i] + ".\n"); }
-
- if (m->getControl_pressed()) { break; }
-
- string simpleName1 = util.getRootName(util.getSimpleName(fastqFiles[i]));
- string simpleName2 = util.getRootName(util.getSimpleName(fastqFiles[i+1]));
-
- //possible pair
- if (simpleName1.length() == simpleName2.length()) {
- int numDiffs = 0;
- for (int j = 0; j < simpleName1.length(); j++) {
- if (numDiffs > 1) { break; }
- else if (simpleName1[j] != simpleName2[j]) { numDiffs++; }
- }
- if (numDiffs > 1) { singles.push_back(util.getSimpleName(fastqFiles[i])); lastFile = fastqFiles[i]; }
- else { //only one diff = paired files
- vector<string> temp;
- temp.push_back(util.getSimpleName(fastqFiles[i])); temp.push_back(util.getSimpleName(fastqFiles[i+1])); lastFile = fastqFiles[i+1];
- if (m->getDebug()) { m->mothurOut("[DEBUG]: Pairing " + fastqFiles[i] + " with " + fastqFiles[i+1] + ".\n"); }
- paired.push_back(temp);
- i++;
- }
- }else{
- if (m->getDebug()) { m->mothurOut("[DEBUG]: Adding single " + fastqFiles[i] + ".\n"); }
- singles.push_back(util.getSimpleName(fastqFiles[i])); lastFile = fastqFiles[i];
- }
+ vector< vector<string> > paired = pairFiles(files, singles);
+ outputs = prepareOutputs(paired);
+ }else {
+ outputs = prepareOutputs(files);
+ }
+
+ for (int i = 0; i < outputs.size(); i++) {
+ for (int j = 0; j < outputs[i].size(); j++) { out << outputs[i][j] << '\t'; } out << endl;
+ }
+ out.close();
+ }
+ catch(exception& e) {
+ m->errorOut(e, "MakeFileCommand", "createFastaFile");
+ exit(1);
+ }
+}
+//**********************************************************************************************************************
+
+void MakeFileCommand::createFastqGzFile(vector<string> files){
+ try {
+ vector<string> singles;
+ vector< vector<string> > paired = pairFiles(files, singles);
+
+ if (singles.size() != 0) {
+ map<string, string> variables;
+ variables["[filename]"] = outputdir + prefix + ".";
+ if (paired.size() != 0) { variables["[tag]"] = "single"; }
+ string filename = getOutputFileName("file",variables);
+
+ ofstream out; util.openOutputFile(filename, out);
+
+ for (int i = 0; i < singles.size(); i++) { out << singles[i] << endl; } out.close();
+
+ if (util.isBlank(filename)) { util.mothurRemove(filename); }
+ else {
+ outputNames.push_back(filename); outputTypes["file"].push_back(filename);
+ m->mothurOut("\n[WARNNG]: mothur found unpaired files in your input directory. Outputting list of filenames to " + filename + " for your review.\n\n");
}
- if (lastFile != fastqFiles[fastqFiles.size()-1]) {
- if (m->getDebug()) { m->mothurOut("[DEBUG]: Adding single " + fastqFiles[fastqFiles.size()-1] + ".\n"); }
- singles.push_back(util.getSimpleName(fastqFiles[fastqFiles.size()-1])); }
+ }
+
+ //generates unique group names
+ if (numCols == 3) { paired = prepareOutputs(paired); }
+
+ if (paired.size() != 0) {
+ map<string, string> variables;
+ variables["[filename]"] = outputdir + prefix + ".";
+ string filename = getOutputFileName("file",variables);
- if (singles.size() != 0) {
- map<string, string> variables;
- variables["[filename]"] = outputdir + prefix + ".";
- if (paired.size() != 0) { variables["[tag]"] = "single"; }
- string filename = getOutputFileName("file",variables);
-
- ofstream out; util.openOutputFile(filename, out);
-
- for (int i = 0; i < singles.size(); i++) { out << singles[i] << endl; } out.close();
-
- if (util.isBlank(filename)) { util.mothurRemove(filename); }
- else {
- outputNames.push_back(filename); outputTypes["file"].push_back(filename);
- m->mothurOut("\n[WARNNG]: mothur found unpaired files in your input directory. Outputting list of filenames to " + filename + " for your review.\n\n");
- }
+ ofstream out; util.openOutputFile(filename, out);
+ outputNames.push_back(filename); outputTypes["file"].push_back(filename);
+ current->setFileFile(filename);
+
+ for (int i = 0; i < paired.size(); i++) {
+ for (int j = 0; j < paired[i].size(); j++) { out << paired[i][j] << '\t'; } out << endl;
}
+ out.close();
+ }
+ }
+ catch(exception& e) {
+ m->errorOut(e, "MakeFileCommand", "createFastqGzFile");
+ exit(1);
+ }
+}
+//**********************************************************************************************************************
+vector< vector<string> > MakeFileCommand::pairFiles(vector<string> files, vector<string>& singles){
+ try {
+ vector< vector<string> > paired;
+ string lastFile = "";
+
+ for (int i = 0; i < files.size()-1; i++) {
- //generates unique group names
- if (numCols == 3) { paired = findGroupNames(paired); }
-
- if (paired.size() != 0) {
- map<string, string> variables;
- variables["[filename]"] = outputdir + prefix + ".";
- string filename = getOutputFileName("file",variables);
-
- ofstream out; util.openOutputFile(filename, out);
- outputNames.push_back(filename); outputTypes["file"].push_back(filename);
- current->setFileFile(filename);
-
- for (int i = 0; i < paired.size(); i++) {
- for (int j = 0; j < paired[i].size(); j++) { out << paired[i][j] << '\t'; } out << endl;
+ if (m->getDebug()) { m->mothurOut("[DEBUG]: File " + toString(i) + " = " + files[i] + ".\n"); }
+
+ if (m->getControl_pressed()) { break; }
+
+ string simpleName1 = util.getRootName(util.getSimpleName(files[i]));
+ string simpleName2 = util.getRootName(util.getSimpleName(files[i+1]));
+
+ //possible pair
+ if (simpleName1.length() == simpleName2.length()) {
+ int numDiffs = 0;
+ for (int j = 0; j < simpleName1.length(); j++) {
+ if (numDiffs > 1) { break; }
+ else if (simpleName1[j] != simpleName2[j]) { numDiffs++; }
+ }
+ if (numDiffs > 1) { singles.push_back(util.getSimpleName(files[i])); lastFile = files[i]; }
+ else { //only one diff = paired files
+ vector<string> temp;
+ temp.push_back(util.getSimpleName(files[i])); temp.push_back(util.getSimpleName(files[i+1])); lastFile = files[i+1];
+ if (m->getDebug()) { m->mothurOut("[DEBUG]: Pairing " + files[i] + " with " + files[i+1] + ".\n"); }
+ paired.push_back(temp);
+ i++;
}
- out.close();
+ }else{
+ if (m->getDebug()) { m->mothurOut("[DEBUG]: Adding single " + files[i] + ".\n"); }
+ singles.push_back(util.getSimpleName(files[i])); lastFile = files[i];
}
-
}
- if (m->getControl_pressed()) { for (int i = 0; i < outputNames.size(); i++) { util.mothurRemove(outputNames[i]); } return 0; }
- m->mothurOut("\nOutput File Names: \n");
- for (int i = 0; i < outputNames.size(); i++) { m->mothurOut(outputNames[i]+"\n"); }
- m->mothurOutEndLine();
+ if (lastFile != files[files.size()-1]) {
+ if (m->getDebug()) { m->mothurOut("[DEBUG]: Adding single " + files[files.size()-1] + ".\n"); }
+ singles.push_back(util.getSimpleName(files[files.size()-1]));
+ }
+
+ return paired;
- return 0;
}
catch(exception& e) {
- m->errorOut(e, "MakeFileCommand", "execute");
+ m->errorOut(e, "MakeFileCommand", "pairFiles");
+ exit(1);
+ }
+}
+//**********************************************************************************************************************
+//groupName defaults to "noGroup"+toString(i);
+vector< vector<string> > MakeFileCommand::prepareOutputs(vector<string> files){
+ try {
+ vector< vector<string> > results; results.resize(files.size());
+
+ vector<string> groupNames;
+ if (delim == "*") {
+ groupNames = denoiseGroupNames(files);
+ }else {
+ groupNames = createDefaultGroupNames(files);
+ }
+
+ for (int i = 0; i < files.size(); i++) {
+ results[i].push_back(groupNames[i]); results[i].push_back(util.getSimpleName(files[i]));
+ }
+
+ return results;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "MakeFileCommand", "prepareOutputs");
exit(1);
}
}
//**********************************************************************************************************************
//groupName defaults to "noGroup"+toString(i);
-vector< vector<string> > MakeFileCommand::findGroupNames(vector< vector<string> > paired){
+vector< vector<string> > MakeFileCommand::prepareOutputs(vector< vector<string> > paired){
try {
vector< vector<string> > results; results.resize(paired.size());
+ vector<string> forwardNames;
+ for (int i = 0; i < paired.size(); i++) {
+ forwardNames.push_back(util.getRootName(util.getSimpleName(paired[i][0])));
+ }
+
+ vector<string> groupNames;
if (delim == "*") {
- //remove any "words" in filenames that is the same in all filenames separated by delim(_ .)
- //MI.M00833_0261.001.FLD0207.TRIN-META_16S_R2.fastq
- //MI.M00833_0261.001.FLD0223.ERIFF-META_16S_R2.fastq
- //would become...
- //FLD0207.TRIN-META
- //FLD0223.ERIFF-META
+ groupNames = denoiseGroupNames(forwardNames);
+ }else {
+ groupNames = createDefaultGroupNames(forwardNames);
+ }
+
+ for (int i = 0; i < paired.size(); i++) {
+ results[i].push_back(groupNames[i]); results[i].push_back(paired[i][0]); results[i].push_back(paired[i][1]);
+ }
+
+ return results;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "MakeFileCommand", "prepareOutputs");
+ exit(1);
+ }
+}
+//**********************************************************************************************************************
+
+vector<string> MakeFileCommand::createDefaultGroupNames(vector<string> files){
+ try {
+ set<string> groups;
+ vector<string> groupNames;
+ for (int i = 0; i < files.size(); i++) {
- //split all forward names into pieces
- vector<vector<string> > words; words.resize(paired.size());
- map<int, set<string> > posToWord;
+ string groupName = "Group_" + toString(i);
+ string filename = util.getSimpleName(files[i]);
+ int pos = filename.find(delim);
- for (int i = 0; i < paired.size(); i++) {
- if (m->getControl_pressed()) { break; }
-
- string filename = util.getRootName(util.getSimpleName(paired[i][0]));
-
- int pos = 0;
- string individual = "";
- for(int j=0;j<filename.length();j++){
- if((filename[j] == '.') || (filename[j] == '_')){
- words[i].push_back(individual);
-
- map<int, set<string> >::iterator it = posToWord.find(pos);
- if (it != posToWord.end()) { posToWord[pos].insert(individual); }
- else {
- set<string> temp; temp.insert(individual);
- posToWord[pos] = temp;
- }
- individual = "";
- pos++;
- }
- else{
- individual += filename[j];
- }
+ if (pos != string::npos) { groupName = filename.substr(0, pos); }
+
+ if (groups.count(groupName) == 0) { util.checkName(groupName); groups.insert(groupName); }
+ else {
+ //look for another delim
+ string tempFilename = filename.substr(pos+1); //grab rest of name
+ pos = tempFilename.find(delim);
+ if (pos != string::npos) {
+ groupName += "_" + tempFilename.substr(0, pos);
+ if (groups.count(groupName) != 0) { groupName += "_"+ toString(i); } //already have this name
}
- if (!util.allSpaces(individual)) {
+ else { groupName += "_"+ toString(i); }
+ util.checkName(groupName);
+ groups.insert(groupName);
+ }
+
+ groupNames.push_back(groupName);
+ }
+
+ return groupNames;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "MakeFileCommand", "createGroupNames");
+ exit(1);
+ }
+}
+//**********************************************************************************************************************
+
+vector<string> MakeFileCommand::denoiseGroupNames(vector<string> files){
+ try {
+ //remove any "words" in filenames that is the same in all filenames separated by delim(_ .)
+ //MI.M00833_0261.001.FLD0207.TRIN-META_16S_R2.fastq
+ //MI.M00833_0261.001.FLD0223.ERIFF-META_16S_R2.fastq
+ //would become...
+ //FLD0207.TRIN-META
+ //FLD0223.ERIFF-META
+
+ //split all names into pieces
+ vector<vector<string> > words; words.resize(files.size());
+ map<int, set<string> > posToWord;
+
+ for (int i = 0; i < files.size(); i++) {
+ if (m->getControl_pressed()) { break; }
+
+ string filename = util.getRootName(util.getSimpleName(files[i]));
+
+ int pos = 0;
+ string individual = "";
+ for(int j=0;j<filename.length();j++){
+ if((filename[j] == '.') || (filename[j] == '_')){
words[i].push_back(individual);
+
map<int, set<string> >::iterator it = posToWord.find(pos);
if (it != posToWord.end()) { posToWord[pos].insert(individual); }
else {
set<string> temp; temp.insert(individual);
posToWord[pos] = temp;
}
+ individual = "";
+ pos++;
}
- }
-
- //remove duplicate pieces
- set<int> goodIndexes;
- for (map<int, set<string> >::iterator it = posToWord.begin(); it != posToWord.end(); it++) {
- set<string> w = it->second;;
- if (w.size() != 1) { goodIndexes.insert(it->first); }
- }
-
- set<string> groups;
- for (int i = 0; i < words.size(); i++) {
-
- //assemble groupNames
- string groupName = "";
- for (int j = 0; j < words[i].size(); j++) {
- //include word
- if (goodIndexes.count(j) != 0) { groupName += words[i][j] + "_"; }
+ else{
+ individual += filename[j];
}
-
- if (groupName != "") { groupName = groupName.substr(0, groupName.length()-1); }
-
- //is this name unique
- if (groups.count(groupName) == 0) { util.checkName(groupName); groups.insert(groupName); }
- else { groupName = "Group_"+ toString(i); util.checkName(groupName); groups.insert(groupName); }
-
- results[i].push_back(groupName); results[i].push_back(paired[i][0]); results[i].push_back(paired[i][1]);
}
-
- }else { //separate by the user selected deliminator. default='_'
- set<string> groups;
- for (int i = 0; i < paired.size(); i++) {
-
- string groupName = "Group_" + toString(i);
- string filename = util.getSimpleName(paired[i][0]);
- int pos = filename.find(delim);
-
- if (pos != string::npos) { groupName = filename.substr(0, pos); }
-
- if (groups.count(groupName) == 0) { util.checkName(groupName); groups.insert(groupName); }
+ if (!util.allSpaces(individual)) {
+ words[i].push_back(individual);
+ map<int, set<string> >::iterator it = posToWord.find(pos);
+ if (it != posToWord.end()) { posToWord[pos].insert(individual); }
else {
- //look for another delim
- string tempFilename = filename.substr(pos+1); //grab rest of name
- pos = tempFilename.find(delim);
- if (pos != string::npos) {
- groupName += "_" + tempFilename.substr(0, pos);
- if (groups.count(groupName) != 0) { groupName += "_"+ toString(i); } //already have this name
- }
- else { groupName += "_"+ toString(i); }
- util.checkName(groupName);
- groups.insert(groupName);
+ set<string> temp; temp.insert(individual);
+ posToWord[pos] = temp;
}
-
- results[i].push_back(groupName); results[i].push_back(paired[i][0]); results[i].push_back(paired[i][1]);
}
}
- return results;
+
+ //remove duplicate pieces
+ set<int> goodIndexes;
+ for (map<int, set<string> >::iterator it = posToWord.begin(); it != posToWord.end(); it++) {
+ set<string> w = it->second;;
+ if (w.size() != 1) { goodIndexes.insert(it->first); }
+ }
+
+ set<string> groups;
+ vector<string> orderedGroups;
+ for (int i = 0; i < words.size(); i++) {
+
+ //assemble groupNames
+ string groupName = "";
+ for (int j = 0; j < words[i].size(); j++) {
+ //include word
+ if (goodIndexes.count(j) != 0) { groupName += words[i][j] + "_"; }
+ }
+
+ if (groupName != "") { groupName = groupName.substr(0, groupName.length()-1); }
+
+ //is this name unique
+ if (groups.count(groupName) == 0) { util.checkName(groupName); groups.insert(groupName); }
+ else { groupName = "Group_"+ toString(i); util.checkName(groupName); groups.insert(groupName); }
+
+ orderedGroups.push_back(groupName);
+ }
+
+ return orderedGroups;
}
catch(exception& e) {
- m->errorOut(e, "MakeFileCommand", "findGroupName");
+ m->errorOut(e, "MakeFileCommand", "denoiseGroupNames");
exit(1);
}
}
-
//**********************************************************************************************************************
int MakeFileCommand::fillAccnosFile(string tempFile){
=====================================
source/commands/makefilecommand.h
=====================================
@@ -36,8 +36,15 @@ private:
int numCols;
bool abort;
- vector< vector<string> > findGroupNames(vector< vector<string> > paired);
+ vector< vector<string> > prepareOutputs(vector< vector<string> > paired);
+ vector< vector<string> > prepareOutputs(vector<string> files);
+ vector<string> denoiseGroupNames(vector<string> files);
+ vector<string> createDefaultGroupNames(vector<string> files);
+
int fillAccnosFile(string tempFile);
+ vector< vector<string> > pairFiles(vector<string> files, vector<string>& singles);
+ void createFastqGzFile(vector<string>);
+ void createFastaFile(vector<string>);
};
=====================================
source/commands/makegroupcommand.cpp
=====================================
@@ -10,12 +10,13 @@
#include "makegroupcommand.h"
#include "sequence.hpp"
#include "counttable.h"
-
+#include "filefile.hpp"
//**********************************************************************************************************************
vector<string> MakeGroupCommand::setParameters(){
try {
- CommandParameter pfasta("fasta", "InputTypes", "", "", "none", "none", "none","group",false,true,true); parameters.push_back(pfasta);
+ CommandParameter pfasta("fasta", "InputTypes", "", "", "FastaFastqFile", "FastaFastqFile", "none","count",false,true,true); parameters.push_back(pfasta);
+ CommandParameter pfile("file", "InputTypes", "", "", "FastaFastqFile", "FastaFastqFile", "none","count",false,false,true); parameters.push_back(pfile);
CommandParameter pgroups("groups", "String", "", "", "", "", "","",false,false,true); parameters.push_back(pgroups);
CommandParameter poutput("output", "String", "", "", "", "", "","",false,false); parameters.push_back(poutput);
CommandParameter pformat("format", "Multiple", "count-group", "count", "", "", "","",false,false,true); parameters.push_back(pformat);
@@ -42,13 +43,14 @@ vector<string> MakeGroupCommand::setParameters(){
string MakeGroupCommand::getHelpString(){
try {
string helpString = "";
- helpString += "The make.group (also called make.count) command reads a fasta file or series of fasta files and creates a group file or count file.\n";
- helpString += "The make.group command parameters are fasta, groups, format and output. Fasta and groups are required.\n";
+ helpString += "The make.count (also called make.group) command will create a count or group file.\nThe make.count command reads a file file, fasta file or series of fasta files and creates a group file or count file.\n";
+ helpString += "The make.group command parameters are file, fasta, groups, format and output. File or Fasta and groups are required.\n";
helpString += "The output parameter allows you to specify the name of group file or count file created. \n";
helpString += "The format parameter allows you to specify whether the outputtted file is a group file or count file. Default=count. \n";
- helpString += "The make.group command should be in the following format: \n";
- helpString += "make.group(fasta=yourFastaFiles, groups=yourGroups). \n";
- helpString += "Example make.group(fasta=seqs1.fasta-seq2.fasta-seqs3.fasta, groups=A-B-C)\n";
+ helpString += "The make.count command should be in the following format: \n";
+ helpString += "make.count(file=yourFileFile). \n";
+ helpString += "make.count(fasta=yourFastaFiles, groups=yourGroups). \n";
+ helpString += "Example make.count(fasta=seqs1.fasta-seq2.fasta-seqs3.fasta, groups=A-B-C)\n";
return helpString;
}
catch(exception& e) {
@@ -89,6 +91,10 @@ MakeGroupCommand::MakeGroupCommand(string option) : Command() {
string inputDir = validParameter.validPath(parameters, "inputdir");
if (inputDir == "not found"){ inputDir = ""; }
+ fileFile = validParameter.validFile(parameters, "file");
+ if (fileFile == "not open") { abort = true; }
+ else if (fileFile == "not found") { fileFile = ""; }
+
fastaFileNames = validParameter.validFiles(parameters, "fasta");
if (fastaFileNames.size() != 0) {
if (fastaFileNames[0] == "not open") { abort = true; }
@@ -96,7 +102,7 @@ MakeGroupCommand::MakeGroupCommand(string option) : Command() {
}
//make sure there is at least one valid file left
- if (fastaFileNames.size() == 0) { m->mothurOut("[ERROR]: no valid files.\n"); abort = true; }
+ if ((fileFile == "") && (fastaFileNames.size() == 0)) { m->mothurOut("[ERROR]: no valid files. Please provide a file file or fasta file.\n"); abort = true; }
output = validParameter.validPath(parameters, "output");
if (output == "not found") { output = ""; }
@@ -105,10 +111,14 @@ MakeGroupCommand::MakeGroupCommand(string option) : Command() {
if ((format != "count") && (format != "group")) { m->mothurOut("\n[WARNING]: invalid format option: choices are count or group, using count.\n"); format="count"; }
groups = validParameter.valid(parameters, "groups");
- if (groups == "not found") { m->mothurOut("groups is a required parameter for the make.group command.\n"); abort = true; }
+ if (groups == "not found") {
+ if (fileFile == "") {
+ m->mothurOut("[ERROR]: The groups parameter is required unless you are using a file file.\n"); abort = true;
+ }
+ }
else { util.splitAtDash(groups, groupsNames); }
- if (groupsNames.size() != fastaFileNames.size()) { m->mothurOut("You do not have the same number of valid fastfile files as groups. This could be because we could not open a fastafile.\n"); abort = true; }
+ if ((fileFile == "") && (groupsNames.size() != fastaFileNames.size())) { m->mothurOut("[ERROR]: You do not have the same number of valid fastfile files as groups. This could be because we could not open a fastafile.\n"); abort = true; }
}
}
catch(exception& e) {
@@ -117,50 +127,43 @@ MakeGroupCommand::MakeGroupCommand(string option) : Command() {
}
}
//**********************************************************************************************************************
-
int MakeGroupCommand::execute(){
try {
if (abort) { if (calledHelp) { return 0; } return 2; }
- util.checkGroupNames(groupsNames);
-
- map<string, string> seqGroup; map<string, long long> groupCounts;
- for (int i = 0; i < fastaFileNames.size(); i++) {
+ string outputFileRoot = "";
+ map<string, string> seqGroup;
+ map<string, long long> groupCounts;
+
+ if (fileFile == "") {
+ processFastaFiles(seqGroup, groupCounts);
- if (m->getControl_pressed()) { break; }
+ //if no output filename given, create root
+ if (output == "") {
+ if (outputdir == "") { outputdir = util.hasPath(fastaFileNames[0]); }
+ outputFileRoot = outputdir + util.getRootName(util.getSimpleName(fastaFileNames[0]));
+ if (fastaFileNames.size() > 1) { outputFileRoot = outputdir + "merge."; }
+ }
+ }else {
+ processFileFile(seqGroup, groupCounts);
- m->mothurOutJustToScreen("\nAssigning sequences from file " + fastaFileNames[i] + " to group " + groupsNames[i] + ":\t");
-
- ifstream in; util.openInputFile(fastaFileNames[i], in);
-
- long long count = 0;
- while (!in.eof()) {
-
- if (m->getControl_pressed()) { break; }
-
- Sequence seq(in); gobble(in);
-
- if (seq.getName() != "") { seqGroup[seq.getName()] = groupsNames[i]; count++; }
- }
- in.close();
- m->mothurOutJustToScreen(toString(count) + " sequences assigned to group " + groupsNames[i] + "\n");
- groupCounts[groupsNames[i]] = count;
- }
+ if (output == "") {
+ if (outputdir == "") { outputdir = util.hasPath(fileFile); }
+ outputFileRoot = outputdir + util.getRootName(util.getSimpleName(fileFile));
+ }
+ }
if (m->getControl_pressed()) { return 0; }
//if user provided output filename, then use it
string outputFileName = util.getFullPathName(output);
- //if no output filename given, create one
if (output == "") {
map<string, string> variables;
- if (outputdir == "") { outputdir = util.hasPath(fastaFileNames[0]); }
- variables["[filename]"] = outputdir + util.getRootName(util.getSimpleName(fastaFileNames[0]));
- if (fastaFileNames.size() > 1) { variables["[filename]"] = outputdir + "merge."; }
+ variables["[filename]"] = outputFileRoot;
outputFileName = getOutputFileName(format,variables);
+ outputNames.push_back(outputFileName); outputTypes[format].push_back(outputFileName);
}
- outputNames.push_back(outputFileName); outputTypes[format].push_back(outputFileName);
if (format == "count") {
CountTable ct; ct.createTable(seqGroup);
@@ -200,5 +203,65 @@ int MakeGroupCommand::execute(){
}
}
//**********************************************************************************************************************
+void MakeGroupCommand::processFastaFiles(map<string, string>& seqGroup, map<string, long long>& groupCounts){
+ try {
+
+ util.checkGroupNames(groupsNames);
+
+ for (int i = 0; i < fastaFileNames.size(); i++) {
+
+ if (m->getControl_pressed()) { break; }
+
+ m->mothurOutJustToScreen("\nAssigning sequences from file " + fastaFileNames[i] + " to group " + groupsNames[i] + ":\t");
+
+ ifstream in; util.openInputFile(fastaFileNames[i], in);
+
+ long long count = 0;
+ while (!in.eof()) {
+
+ if (m->getControl_pressed()) { break; }
+
+ Sequence seq(in); gobble(in);
+
+ if (seq.getName() != "") { seqGroup[seq.getName()] = groupsNames[i]; count++; }
+ }
+ in.close();
+ m->mothurOutJustToScreen(toString(count) + " sequences assigned to group " + groupsNames[i] + "\n");
+ groupCounts[groupsNames[i]] = count;
+ }
+ }
+ catch(exception& e) {
+ m->errorOut(e, "MakeGroupCommand", "processFastaFiles");
+ exit(1);
+ }
+}
+//**********************************************************************************************************************
+void MakeGroupCommand::processFileFile(map<string, string>& seqGroup, map<string, long long>& groupCounts){
+ try {
+ FileFile dataFile(fileFile, "make.count");
+ vector< vector<string> > files = dataFile.getFiles();
+ groupsNames = dataFile.getGroupNames();
+ int fileOption = dataFile.getFileFormat(); //7: group -> fastaFile, 8: group -> fowardFasta,reverseFasta
+
+ if (fileOption == 7) {
+ for (auto thisVector : files) {
+ for (auto file : thisVector) {
+ fastaFileNames.push_back(file);
+ }
+ }
+
+ }else {
+ for (auto thisVector : files) {
+ if (thisVector.size() > 0) { fastaFileNames.push_back(thisVector[0]); }
+ }
+ }
+ processFastaFiles(seqGroup, groupCounts);
+ }
+ catch(exception& e) {
+ m->errorOut(e, "MakeGroupCommand", "processFileFile");
+ exit(1);
+ }
+}
+//**********************************************************************************************************************
=====================================
source/commands/makegroupcommand.h
=====================================
@@ -32,11 +32,14 @@ public:
private:
- string fastaFileName, groups, output, format;
+ string fastaFileName, groups, output, format, fileFile;
vector<string> fastaFileNames;
vector<string> groupsNames, outputNames;
bool abort;
+
+ void processFastaFiles(map<string, string>&, map<string, long long>&);
+ void processFileFile(map<string, string>&, map<string, long long>&);
};
#endif
=====================================
source/commands/pcrseqscommand.cpp
=====================================
@@ -812,13 +812,16 @@ int driverPcr(pcrData* params){
if (params->fileAligned && !params->keepdots) { //print out smallest start value and largest end value
if (startLocations.size() > 1) { params->adjustNeeded = true; }
if (endLocations.size() > 1) { params->adjustNeeded = true; }
- if (params->numFPrimers != 0) {
- set<int>::iterator it = startLocations.begin(); params->pstart = *it;
- if (params->m->getDebug()) { params->m->mothurOut("[DEBUG]: " + params->util.getStringFromSet(startLocations, " ")+"\n"); }
- }
- if (params->numRPrimers != 0) {
- set<int>::reverse_iterator it = endLocations.rbegin(); params->pend = *it;
- if (params->m->getDebug()) { params->m->mothurOut("[DEBUG]: " + params->util.getStringFromSet(endLocations, " ")+"\n"); }
+
+ if (params->adjustNeeded) {
+ if (params->numFPrimers != 0) {
+ set<int>::iterator it = startLocations.begin(); params->pstart = *it;
+ if (params->m->getDebug()) { params->m->mothurOut("[DEBUG]: " + params->util.getStringFromSet(startLocations, " ")+"\n"); }
+ }
+ if (params->numRPrimers != 0) {
+ set<int>::reverse_iterator it = endLocations.rbegin(); params->pend = *it;
+ if (params->m->getDebug()) { params->m->mothurOut("[DEBUG]: " + params->util.getStringFromSet(endLocations, " ")+"\n"); }
+ }
}
}
=====================================
source/commands/preclustercommand.cpp
=====================================
@@ -763,6 +763,7 @@ void print(string newfasta, string newname, preClusterData* params){
for (int i = 0; i < params->alignSeqs.size(); i++) {
if (params->alignSeqs[i]->numIdentical != 0) {
ct.push_back(params->alignSeqs[i]->name, params->alignSeqs[i]->numIdentical);
+ accnosNames.insert(params->alignSeqs[i]->name);
}
}
}
=====================================
source/commands/removelineagecommand.cpp
=====================================
@@ -117,7 +117,6 @@ RemoveLineageCommand::RemoveLineageCommand(string option) : Command() {
ValidParameters validParameter;
-
//check for required parameters
fastafile = validParameter.validFile(parameters, "fasta");
if (fastafile == "not open") { fastafile = ""; abort = true; }
@@ -234,13 +233,6 @@ int RemoveLineageCommand::execute(){
if (abort) { if (calledHelp) { return 0; } return 2; }
if (m->getControl_pressed()) { return 0; }
-
- if (countfile != "") {
- if ((fastafile != "") || (listfile != "") || (taxfile != "")) {
- //m->mothurOut("\n[NOTE]: The count file should contain only unique names, so mothur assumes your fasta, list and taxonomy files also contain only uniques.\n\n");
-
- }
- }
//read through the correct file and output lines you want to keep
if (taxfile != "") {
=====================================
source/commands/renameseqscommand.cpp
=====================================
@@ -881,7 +881,7 @@ int RenameSeqsCommand::processFile(){
try {
ignoreNew = true; //if there are sequences only present in some files, ignore them
- map<int, string> file2Group; gz = false;
+ vector<string> file2Group; gz = false;
vector< vector<string> > files = readFiles(file2Group, gz);
string thisOutputDir = outputdir;
@@ -953,12 +953,12 @@ int RenameSeqsCommand::processFile(){
}
}
//**********************************************************************************************************************
-vector< vector<string> > RenameSeqsCommand::readFiles(map<int, string>& file2Group, bool& isGZ){
+vector< vector<string> > RenameSeqsCommand::readFiles(vector<string>& file2Group, bool& isGZ){
try {
FileFile dataFile(fileFile, "contigs");
vector< vector<string> > dataFiles = dataFile.getFiles();
int dataFileFormat = dataFile.getFileFormat();
- file2Group = dataFile.getFile2Group();
+ file2Group = dataFile.getGroupNames();
isGZ = dataFile.isGZ();
if (file2Group.size() == 0) { m->setControl_pressed(true); }
=====================================
source/commands/renameseqscommand.h
=====================================
@@ -51,7 +51,7 @@ private:
string readFastq(map<string, string>&);
int processFile();
int readMapFile(map<string, string>&);
- vector< vector<string> > readFiles(map<int, string>&, bool&);
+ vector< vector<string> > readFiles(vector<string>&, bool&);
void processNameGroupCountFiles(map<string, string>&, map<string, string>&);
};
=====================================
source/commands/setcurrentcommand.cpp
=====================================
@@ -431,6 +431,10 @@ int SetCurrentCommand::readCurrentFiles(){
current->setAccnosFile(util.getFullPathName(pieces[1]));
}else if (pieces[0] == "taxonomy") {
current->setTaxonomyFile(util.getFullPathName(pieces[1]));
+ }else if (pieces[0] == "constaxonomy") {
+ current->setConsTaxonomyFile(util.getFullPathName(pieces[1]));
+ }else if (pieces[0] == "contigsreport") {
+ current->setContigsReportFile(util.getFullPathName(pieces[1]));
}else if (pieces[0] == "flow") {
current->setFlowFile(util.getFullPathName(pieces[1]));
}else if (pieces[0] == "biom") {
@@ -443,6 +447,7 @@ int SetCurrentCommand::readCurrentFiles(){
current->setFileFile(util.getFullPathName(pieces[1]));
}else if (pieces[0] == "processors") {
current->setProcessors(pieces[1]);
+
}else {
m->mothurOut("[ERROR]: mothur does not save a current file for " + util.getFullPathName(pieces[1])); m->mothurOutEndLine();
}
=====================================
source/commands/sracommand.cpp
=====================================
@@ -911,7 +911,7 @@ int SRACommand::readFile(map<string, vector<string> >& files){
FileFile dataFile(inputfile, "sra");
vector< vector<string> > dataFiles = dataFile.getFiles();
int dataFileFormat = dataFile.getFileFormat();
- map<int, string> file2Group = dataFile.getFile2Group();
+ vector<string> file2Group = dataFile.getGroupNames();
if (dataFile.containsIndexFiles() && (!setOligosParameter)) { m->mothurOut("[ERROR]: You must have an oligosfile with the index file option. Aborting. \n"); m->setControl_pressed(true); }
=====================================
source/commands/subsamplecommand.cpp
=====================================
@@ -99,7 +99,7 @@ string SubSampleCommand::getOutputPattern(string type) {
else if (type == "tree") { pattern = "[filename],subsample,[extension]"; }
else if (type == "list") { pattern = "[filename],[distance],subsample,[extension]"; }
else if (type == "taxonomy") { pattern = "[filename],subsample,[extension]"; }
- else if (type == "constaxonomy"){ pattern = "[filename],subsample,[extension]"; }
+ else if (type == "constaxonomy"){ pattern = "[filename],subsample,cons.taxonomy"; }
else if (type == "shared") { pattern = "[filename],[distance],subsample,[extension]"; }
else if (type == "rabund") { pattern = "[filename],subsample,[extension]"; }
else { m->mothurOut("[ERROR]: No definition for type " + type + " output pattern.\n"); m->setControl_pressed(true); }
@@ -770,7 +770,6 @@ int SubSampleCommand::processShared(SharedRAbundVectors*& thislookup) {
if (outputdir == "") { thisOutputDir += util.hasPath(constaxonomyfile); }
map<string, string> variables;
variables["[filename]"] = thisOutputDir + util.getRootName(util.getSimpleName(constaxonomyfile));
- variables["[extension]"] = util.getExtension(constaxonomyfile);
variables["[distance]"] = thislookup->getLabel();
string consOutputFileName = getOutputFileName("constaxonomy", variables);
@@ -1106,7 +1105,6 @@ int SubSampleCommand::processList(ListVector*& list, set<string>& subset) {
if (outputdir == "") { thisOutputDir += util.hasPath(constaxonomyfile); }
map<string, string> variables;
variables["[filename]"] = thisOutputDir + util.getRootName(util.getSimpleName(constaxonomyfile));
- variables["[extension]"] = util.getExtension(constaxonomyfile);
variables["[distance]"] = list->getLabel();
string consOutputFileName = getOutputFileName("constaxonomy", variables);
=====================================
source/datastructures/filefile.cpp
=====================================
@@ -31,101 +31,135 @@ FileFile::FileFile(string f, string md) : filename(f), mode(md) {
}
/**************************************************************************************************
-FileFile::FileFile(){
- try {
- m = MothurOut::getInstance();
-
- current = CurrentFile::getInstance();
- inputDir = current->getInputDir();
- mpath = current->getProgramPath();
-
- fileOption = 0;
- gz = false;
- hasIndex = false;
- filename = ""; mode = "";
- }
- catch(exception& e) {
- m->errorOut(e, "FileFile", "FileFile");
- exit(1);
- }
-}
-
- file option 1
-
- sfffile1 oligosfile1
- sfffile2 oligosfile2
- ...
-
- file option 2
-
- fastqfile1 oligosfile1
- fastqfile2 oligosfile2
- ...
-
- file option 3
-
- ffastqfile1 rfastqfile1
- ffastqfile2 rfastqfile2
- ...
-
- file option 4
-
- group fastqfile fastqfile
- group fastqfile fastqfile
- group fastqfile fastqfile
- ...
-
- file option 5
-
- My.forward.fastq My.reverse.fastq none My.rindex.fastq //none is an option is no forward or reverse index file
- ...
- */
+ /*
+ file option 1
+
+ sfffile1 oligosfile1
+ sfffile2 oligosfile2
+ ...
+
+ file option 2
+
+ fastqfile1 oligosfile1
+ fastqfile2 oligosfile2
+ ...
+
+ file option 3
+
+ ffastqfile1 rfastqfile1
+ ffastqfile2 rfastqfile2
+ ...
+
+ file option 4 - only vaild if mode is set to parsefastqpacbio
+
+ group1 pacBiofastqfile1
+ group2 pacBiofastqfile2
+ ...
+
+ file option 5
+
+ group fastqfile fastqfile
+ group fastqfile fastqfile
+ group fastqfile fastqfile
+ ...
+
+ file option 6
+
+ My.forward.fastq My.reverse.fastq none My.rindex.fastq //none is an option is no forward or reverse index file
+ ...
+
+ file option 7 - for make.count command
+
+ group fastafile
+
+ file option 8 - for make.count command
+
+ group forwardFasta reverseFasta
+
+ */
/**************************************************************************************************/
-vector< vector<string> > FileFile::read(string f, string mode){
+void FileFile::read(string f, string mode){
try {
- filename = f;
-
- bool allGZ = true; bool allPlainTxt = true;
-
- ifstream in; util.openInputFile(filename, in);
-
- while(!in.eof()) {
-
- if (m->getControl_pressed()) { return files; }
+
+ filename = f;
- bool skip = false;
- string line = util.getline(in); gobble(in);
+ bool allGZ = true; bool allPlainTxt = true;
- if (m->getDebug()) { m->mothurOut("[DEBUG]: " + line +"\n"); }
+ ifstream in; util.openInputFile(filename, in);
- if(line[0] == '#'){ } //ignore
- else {
+ while(!in.eof()) {
+
+ if (m->getControl_pressed()) { break; }
- vector<string> pieces = util.splitWhiteSpace(line);
+ bool skip = false;
+ string line = util.getline(in); gobble(in);
- string group = ""; string forward, reverse, findex, rindex;
- skip = validateFiles(pieces, forward, reverse, findex, rindex, group);
+ if (m->getDebug()) { m->mothurOut("[DEBUG]: " + line +"\n"); }
- if (!skip) { //good pair
- file2Group[files.size()] = group;
- if (((findex != "") || (rindex != ""))) { hasIndex = true; }
+ if(line[0] == '#'){ } //ignore
+ else {
- if ((mode == "contigs") || (mode == "sra")) { setGZ(forward, reverse, findex, rindex, allGZ, allPlainTxt); }
+ vector<string> pieces = util.splitWhiteSpace(line);
- vector<string> pair;
- pair.push_back(forward); pair.push_back(reverse); pair.push_back(findex); pair.push_back(rindex);
- files.push_back(pair);
+ if (mode == "make.count") {
+ vector<string> thisGroupsFiles;
+
+ if ((pieces.size() == 2) || (pieces.size() == 3)) {
+ util.checkGroupName(pieces[0]);
+ bool skip = false;
+
+ //check to make fasta file opens
+ bool ableToOpen = util.checkLocations(pieces[1], current->getLocations());
+ if (ableToOpen) {
+ if (util.isBlank(pieces[1])) { m->mothurOut("[WARNING]: " + pieces[1] + " is blank, skipping.\n"); skip=true; }
+ }else { m->mothurOut("[WARNING]: can't find " + pieces[1] + ", ignoring.\n"); skip = true; }
+
+ if (pieces.size() == 3) {
+ //check to make fasta file opens
+ ableToOpen = util.checkLocations(pieces[2], current->getLocations());
+ if (ableToOpen) {
+ if (util.isBlank(pieces[2])) { m->mothurOut("[WARNING]: " + pieces[2] + " is blank, skipping.\n"); skip=true; }
+ }else { m->mothurOut("[WARNING]: can't find " + pieces[2] + ", ignoring.\n"); skip = true; }
+ }
+
+ if (!skip) {
+ groupNames.push_back(pieces[0]);
+ thisGroupsFiles.push_back(pieces[1]);
+ if (pieces.size() == 3) { thisGroupsFiles.push_back(pieces[2]); }
+ files.push_back(thisGroupsFiles);
+ }
+
+ }else {
+ m->mothurOut("[ERROR]: Found " + toString(pieces.size()) + " columns. mothur expects the file file for make.count to be in 2 or 3 column form. \n");
+ }
+ }else {
+ string group = ""; string forward, reverse, findex, rindex;
+ skip = validateFiles(pieces, forward, reverse, findex, rindex, group);
+
+ if (!skip) { //good pair
+ groupNames.push_back(group);
+ if (((findex != "") || (rindex != ""))) { hasIndex = true; }
+
+ if ((mode == "contigs") || (mode == "sra")) { setGZ(forward, reverse, findex, rindex, allGZ, allPlainTxt); }
+
+ vector<string> pair;
+ pair.push_back(forward); pair.push_back(reverse); pair.push_back(findex); pair.push_back(rindex);
+ files.push_back(pair);
+ }
+ }
}
}
- }
- in.close();
-
- if ((mode == "contigs") || (mode == "sra")){ if (allGZ) { gz = true; } else { gz = false; } }
+ in.close();
+
+ if ((mode == "contigs") || (mode == "sra")){ if (allGZ) { gz = true; } else { gz = false; } }
+
+ if (files.size() == 0) { m->setControl_pressed(true); return; }
- if (files.size() == 0) { m->setControl_pressed(true); }
+ if (mode == "make.count") {
+ fileOption = 6 + (int)files[0].size(); //either 1 or 2
+ }
- return files;
}
catch(exception& e) {
m->errorOut(e, "FileFile", "read");
=====================================
source/datastructures/filefile.hpp
=====================================
@@ -50,7 +50,13 @@
My.forward.fastq My.reverse.fastq none My.rindex.fastq //none is an option is no forward or reverse index file
...
+ file option 7 - for make.count command
+ group fastafile
+
+ file option 8 - for make.count command
+
+ group forwardFasta reverseFasta
********* fileOption; //1 -> 2 column(4 forms of 2 column), 2 -> 3 column, 3 -> 4 column ******************
*/
@@ -69,7 +75,7 @@ public:
bool isGZ() { return gz; } //are files listed in file compressed
bool containsIndexFiles() { return hasIndex; } //indicates oligos file is required
- map<int, string> getFile2Group() { return file2Group; } //fileIndex2GroupName, files[0]'s group is -> file2Group[0]
+ vector<string> getGroupNames() { return groupNames; } //fileIndex2GroupName, files[0]'s group is -> groupNames[0]
protected:
@@ -80,9 +86,9 @@ protected:
bool gz, hasIndex, columnWithGroups;
int fileOption; //1 -> 2 column(3 forms of 2 column), 2 -> 3 column, 3 -> 4 column
vector< vector<string> > files;
- map<int, string> file2Group;
+ vector<string> groupNames;
- vector< vector<string> > read(string, string); //read file, used with () constructor
+ void read(string, string); //read file, used with () constructor
bool validateFiles(vector<string> pieces, string& forward, string& reverse, string& findex, string& rindex, string& group); //checks locations, abletoOPen, fileOPtion
void setGZ(string forward, string reverse, string findex, string rindex, bool&, bool&);
};
=====================================
source/datastructures/oligos.cpp
=====================================
@@ -220,6 +220,8 @@ int Oligos::readOligos(){
string type, oligo, roligo, group;
bool pfUsesNone = false; bool prUsesNone = false; bool bfUsesNone = false; bool brUsesNone = false;
+ set<string> uniqueBarcodes;
+ set<string> uniquePrimers;
while(!inOligos.eof()){
@@ -566,6 +568,7 @@ vector<string> Oligos::getPrimers(string groupName){
map<int, oligosPair> Oligos::getReversedPairedPrimers(){
try {
map<int, oligosPair> rpairedPrimers;
+ set<string> uniquePrimers;
for (map<int, oligosPair>::iterator it = pairedPrimers.begin(); it != pairedPrimers.end(); it++) {
//add reverse compliment barcodes
@@ -607,6 +610,7 @@ map<int, oligosPair> Oligos::getReversedPairedPrimers(){
map<int, oligosPair> Oligos::getReorientedPairedPrimers(){
try {
map<int, oligosPair> rpairedPrimers;
+ set<string> uniquePrimers;
for (map<int, oligosPair>::iterator it = pairedPrimers.begin(); it != pairedPrimers.end(); it++) {
string forward = (it->second).reverse;
@@ -703,6 +707,7 @@ map<string, int> Oligos::getReversedPrimers(){
map<int, oligosPair> Oligos::getReversedPairedBarcodes(){
try {
map<int, oligosPair> rpairedBarcodes;
+ set<string> uniqueBarcodes;
for (map<int, oligosPair>::iterator it = pairedBarcodes.begin(); it != pairedBarcodes.end(); it++) {
//add reverse compliment barcodes
@@ -744,6 +749,7 @@ map<int, oligosPair> Oligos::getReversedPairedBarcodes(){
map<int, oligosPair> Oligos::getReorientedPairedBarcodes(){
try {
map<int, oligosPair> rpairedBarcodes;
+ set<string> uniqueBarcodes;
for (map<int, oligosPair>::iterator it = pairedBarcodes.begin(); it != pairedBarcodes.end(); it++) {
string forward = (it->second).reverse;
=====================================
source/datastructures/oligos.h
=====================================
@@ -84,8 +84,6 @@ protected:
int indexBarcode;
int indexPairedPrimer;
int indexPairedBarcode;
- set<string> uniquePrimers;
- set<string> uniqueBarcodes;
int readOligos();
string reverseOligo(string);
=====================================
source/datastructures/sequence.cpp
=====================================
@@ -353,6 +353,7 @@ string Sequence::getSequenceString(ifstream& fastaFile, int& numAmbig) {
//iterate through string
for_each(line.begin(), line.end(), [&numAmbig](char & c) {
c = ::toupper(c);
+ if(c == 'U'){c = 'T';}
if(c != '.' && c != '-' && c != 'A' && c != 'T' && c != 'G' && c != 'C' && c != 'N'){
c = 'N';
numAmbig++;
=====================================
source/validparameter.cpp
=====================================
@@ -202,7 +202,10 @@ string ValidParameters::valid(map<string, string>& container, string parameter)
it = container.find(parameter);
if(it != container.end()){
- Utils util; it->second = util.getSimpleName(it->second); //remove path from non file options
+
+ if (it->first == "order") {
+ Utils util; it->second = util.getSimpleName(it->second); //remove path from order because it refers to floworder not order file
+ }
}
else { return "not found"; }
View it on GitLab: https://salsa.debian.org/med-team/mothur/-/commit/610156ad98ab8077ae0201c36f35c5c6eefb02a6
--
This project does not include diff previews in email notifications.
View it on GitLab: https://salsa.debian.org/med-team/mothur/-/commit/610156ad98ab8077ae0201c36f35c5c6eefb02a6
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20240602/fbef7eb4/attachment-0001.htm>
More information about the debian-med-commit
mailing list