1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
#include "SoloFeature.h"
#include "streamFuns.h"
#include "TimeFunctions.h"
#include "serviceFuns.cpp"
#include "SequenceFuns.h"
#include "ErrorWarning.h"
#include "SoloFeatureTypes.h"
void SoloFeature::outputResults(bool cellFilterYes, string outputPrefixMat)
{
//make directories
createDirectory(outputPrefixMat,P.runDirPerm, "Solo output directory", P);
/* old way, does not work when parent directores are needed
if (mkdir(outputPrefixMat.c_str(),P.runDirPerm)!=0 && errno!=EEXIST) {//create directory
exitWithError("EXITING because of fatal OUTPUT FILE error: could not create Solo output directory" + outputPrefixMat +
"\nSOLUTION: check the path and permisssions\n",
std::cerr, P.inOut->logMain, EXIT_CODE_PARAMETER, P);
};
*/
/////////////////////////////////////////////////////////////
//write features.tsv
switch (featureType) {
case SoloFeatureTypes::Gene :
case SoloFeatureTypes::GeneFull :
case SoloFeatureTypes::Velocyto :
case SoloFeatureTypes::VelocytoSimple :
{
ofstream &geneStr=ofstrOpen(outputPrefixMat+pSolo.outFileNames[1],ERROR_OUT, P);
for (uint32 ii=0; ii<Trans.nGe; ii++) {
geneStr << Trans.geID[ii] <<"\t"<< (Trans.geName[ii].empty() ? Trans.geID[ii] : Trans.geName[ii]);
if (pSolo.outFormat.featuresGeneField3!="-") {
geneStr <<'\t'<< pSolo.outFormat.featuresGeneField3;
};
geneStr << '\n';
};
geneStr.close();
break;
};
case SoloFeatureTypes::SJ :
symlink("../../../SJ.out.tab", (outputPrefixMat+pSolo.outFileNames[1]).c_str());
};
////////////////////////////////////////////////////////////////////////////
//write barcodes.tsv
ofstream &cbStr=ofstrOpen(outputPrefixMat+pSolo.outFileNames[2],ERROR_OUT, P);
uint64 nCellGeneEntries=0;//total number of non-zero cell/gene combinations (entries in the output matrix)
if (cellFilterYes) {//filtered cells
for (uint32 icb=0; icb<nCB; icb++) {
if (filteredCells.filtVecBool[icb]) {
cbStr << pSolo.cbWLstr[indCB[icb]] <<'\n';
nCellGeneEntries += nGenePerCB[icb];
};
};
} else {//unfiltered cells
for (uint64 ii=0; ii<pSolo.cbWLsize; ii++) {
cbStr << pSolo.cbWLstr[ii] <<'\n';
};
for (uint32 icb=0; icb<nCB; icb++) {
nCellGeneEntries += nGenePerCB[icb];
};
};
cbStr.flush();
/////////////////////////////////////////////////////////////
//output counting matrix
for (uint32_t iCol=1; iCol<countMatStride; iCol++) {
string matrixFileName=outputPrefixMat;
if (featureType == SoloFeatureTypes::Velocyto) {
const array<string,3> velonames = {"spliced.mtx", "unspliced.mtx", "ambiguous.mtx"};
matrixFileName += velonames[iCol-1];
} else if (iCol>1 && cellFilterYes) {
break; //if cellFilterYes, only output first iCol, since filtering is only done for it
} else if (pSolo.umiDedup.types.size()>1) {
matrixFileName += "umiDedup-" + pSolo.umiDedup.typeNames[pSolo.umiDedup.types[iCol-1]] + ".mtx";
} else {
matrixFileName += pSolo.outFileNames[3];
};
ofstream &countMatrixStream=ofstrOpen(matrixFileName,ERROR_OUT, P);
//header
countMatrixStream <<"%%MatrixMarket matrix coordinate integer general\n";
countMatrixStream <<"%\n";
countMatrixStream << featuresNumber <<' '<< (cellFilterYes ? filteredCells.nCells : pSolo.cbWLsize) <<' '<< nCellGeneEntries << '\n';
uint32 cbInd1=0;
for (uint32 icb=0; icb<nCB; icb++) {
if (cellFilterYes) {
if (filteredCells.filtVecBool[icb]) {
++cbInd1;
} else {
continue;
};
} else {
cbInd1=indCB[icb]+1;
};
for (uint32 ig=0; ig<nGenePerCB[icb]; ig++) {
uint32 indG1=countCellGeneUMIindex[icb]+ig*countMatStride;
//feature index, CB index, count
countMatrixStream << countCellGeneUMI[indG1]+1 <<' '<< cbInd1 <<' '<< countCellGeneUMI[indG1+iCol] << '\n';
};
};
countMatrixStream.close();
};
};
|