1 /**
2 * UGENE - Integrated Bioinformatics Tools.
3 * Copyright (C) 2008-2021 UniPro <ugene@unipro.ru>
4 * http://ugene.net
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 #include "CuffmergeSupportTask.h"
23
24 #include <QDir>
25
26 #include <U2Core/AnnotationTableObject.h>
27 #include <U2Core/AppContext.h>
28 #include <U2Core/BaseDocumentFormats.h>
29 #include <U2Core/ExternalToolRegistry.h>
30 #include <U2Core/ExternalToolRunTask.h>
31 #include <U2Core/GUrlUtils.h>
32 #include <U2Core/IOAdapter.h>
33 #include <U2Core/L10n.h>
34 #include <U2Core/LoadDocumentTask.h>
35 #include <U2Core/U2SafePoints.h>
36 #include <U2Core/U2Type.h>
37
38 #include <U2Lang/DbiDataStorage.h>
39
40 #include "CufflinksSupport.h"
41 #include "CufflinksSupportTask.h"
42 #include "tophat/TopHatSettings.h"
43
44 namespace U2 {
45
46 const QString CuffmergeSupportTask::outSubDirBaseName("cuffmerge_out");
47
CuffmergeSupportTask(const CuffmergeSettings & _settings)48 CuffmergeSupportTask::CuffmergeSupportTask(const CuffmergeSettings &_settings)
49 : ExternalToolSupportTask(tr("Running Cuffmerge task"), TaskFlags_FOSE_COSC), settings(_settings),
50 fileNum(0),
51 mergeTask(nullptr),
52 loadResultTask(nullptr) {
53 SAFE_POINT_EXT(nullptr != settings.storage, setError(tr("Workflow data storage is NULL")), );
54 SAFE_POINT_EXT(!settings.annotationTables.isEmpty(), setError(tr("There are no annotations to process")), );
55 }
56
~CuffmergeSupportTask()57 CuffmergeSupportTask::~CuffmergeSupportTask() {
58 qDeleteAll(docs);
59 qDeleteAll(result);
60 }
61
prepare()62 void CuffmergeSupportTask::prepare() {
63 setupWorkingDirPath();
64
65 settings.outDir = GUrlUtils::createDirectory(
66 settings.outDir + "/" + outSubDirBaseName,
67 "_",
68 stateInfo);
69 CHECK_OP(stateInfo, );
70
71 foreach (const Workflow::SharedDbiDataHandler &annTableHandler, settings.annotationTables) {
72 Task *task = createWriteTask(annTableHandler, getAnnsFilePath());
73 CHECK_OP(stateInfo, );
74 addSubTask(task);
75 }
76 }
77
onSubTaskFinished(Task * subTask)78 QList<Task *> CuffmergeSupportTask::onSubTaskFinished(Task *subTask) {
79 if (writeTasks.contains(subTask)) {
80 writeTasks.removeOne(subTask);
81 }
82
83 QList<Task *> newSubTasks;
84 if (writeTasks.isEmpty() && nullptr == mergeTask) {
85 newSubTasks << createCuffmergeTask();
86 }
87
88 else if (subTask == mergeTask) {
89 loadResultTask = createLoadResultDocumentTask("merged.gtf");
90 CHECK_OP(stateInfo, newSubTasks);
91 newSubTasks << loadResultTask;
92 }
93
94 else if (subTask == loadResultTask) {
95 QScopedPointer<Document> doc(loadResultTask->takeDocument());
96 SAFE_POINT_EXT(nullptr != doc, setError(L10N::nullPointerError("document with annotations")), newSubTasks);
97 doc->setDocumentOwnsDbiResources(false);
98 foreach (GObject *object, doc->findGObjectByType(GObjectTypes::ANNOTATION_TABLE)) {
99 doc->removeObject(object, DocumentObjectRemovalMode_Release);
100 result << qobject_cast<AnnotationTableObject *>(object);
101 }
102 }
103
104 return newSubTasks;
105 }
106
run()107 void CuffmergeSupportTask::run() {
108 ExternalToolSupportUtils::appendExistingFile(settings.outDir + "/merged.gtf", outputFiles);
109 }
110
setupWorkingDirPath()111 void CuffmergeSupportTask::setupWorkingDirPath() {
112 if (0 == QString::compare(settings.workingDir, "default", Qt::CaseInsensitive)) {
113 workingDir = ExternalToolSupportUtils::createTmpDir(CufflinksSupport::CUFFMERGE_TMP_DIR, stateInfo);
114 } else {
115 workingDir = ExternalToolSupportUtils::createTmpDir(settings.workingDir, CufflinksSupport::CUFFMERGE_TMP_DIR, stateInfo);
116 }
117 }
118
getAnnsFilePath()119 QString CuffmergeSupportTask::getAnnsFilePath() {
120 QString filePath = workingDir + QString("/tmp_%1.gtf").arg(fileNum);
121 fileNum++;
122 return filePath;
123 }
124
createWriteTask(const Workflow::SharedDbiDataHandler & annTableHandler,const QString & filePath)125 Task *CuffmergeSupportTask::createWriteTask(const Workflow::SharedDbiDataHandler &annTableHandler, const QString &filePath) {
126 Document *doc = prepareDocument(annTableHandler, filePath);
127 CHECK_OP(stateInfo, nullptr);
128
129 docs << doc;
130 SaveDocumentTask *task = new SaveDocumentTask(doc, doc->getIOAdapterFactory(), filePath);
131 writeTasks << task;
132
133 return task;
134 }
135
writeFileList()136 void CuffmergeSupportTask::writeFileList() {
137 listFilePath = workingDir + "/gtf_list.txt";
138 QFile file(listFilePath);
139 bool res = file.open(QIODevice::WriteOnly);
140 if (!res) {
141 stateInfo.setError(tr("Can not create a file: %1").arg(listFilePath));
142 return;
143 }
144
145 QString data;
146 foreach (Document *doc, docs) {
147 data += doc->getURLString() + "\n";
148 }
149 file.write(data.toLatin1());
150 file.close();
151 }
152
createCuffmergeTask()153 Task *CuffmergeSupportTask::createCuffmergeTask() {
154 writeFileList();
155 CHECK_OP(stateInfo, nullptr);
156
157 QStringList args;
158 {
159 args << "-p" << QString::number(TopHatSettings::getThreadsCount());
160 if (!settings.refAnnsUrl.isEmpty()) {
161 args << "--ref-gtf" << settings.refAnnsUrl;
162 }
163 if (!settings.refSeqUrl.isEmpty()) {
164 args << "--ref-sequence" << settings.refSeqUrl;
165 }
166 args << "-o" << settings.outDir;
167 args << "--min-isoform-fraction" << QString::number(settings.minIsoformFraction);
168 args << listFilePath;
169 }
170
171 QStringList addPaths;
172 {
173 ExternalToolRegistry *registry = AppContext::getExternalToolRegistry();
174
175 ExternalTool *cm = registry->getById(CufflinksSupport::ET_CUFFMERGE_ID);
176 ExternalTool *cc = registry->getById(CufflinksSupport::ET_CUFFCOMPARE_ID);
177 QFileInfo cmInfo(cm->getPath());
178 QFileInfo ccInfo(cc->getPath());
179
180 addPaths << cmInfo.dir().absolutePath();
181 addPaths << ccInfo.dir().absolutePath();
182 }
183
184 mergeTask = new ExternalToolRunTask(CufflinksSupport::ET_CUFFMERGE_ID, args, new ExternalToolLogParser(), workingDir, addPaths);
185 setListenerForTask(mergeTask);
186 return mergeTask;
187 }
188
createLoadResultDocumentTask(const QString & fileName)189 LoadDocumentTask *CuffmergeSupportTask::createLoadResultDocumentTask(const QString &fileName) {
190 const QString filePath = settings.outDir + "/" + fileName;
191
192 IOAdapterFactory *iof = AppContext::getIOAdapterRegistry()->getIOAdapterFactoryById(BaseIOAdapters::LOCAL_FILE);
193 SAFE_POINT_EXT(nullptr != iof, setError(tr("An internal error occurred during getting annotations from a %1 output file!").arg(CufflinksSupport::ET_CUFFMERGE)), nullptr);
194
195 QVariantMap hints;
196 hints[DocumentFormat::DBI_REF_HINT] = QVariant::fromValue(settings.storage->getDbiRef());
197
198 return new LoadDocumentTask(BaseDocumentFormats::GTF, filePath, iof, hints);
199 }
200
takeResult()201 QList<AnnotationTableObject *> CuffmergeSupportTask::takeResult() {
202 QList<AnnotationTableObject *> ret = result;
203 result.clear();
204 return ret;
205 }
206
prepareDocument(const Workflow::SharedDbiDataHandler & annTableHandler,const QString & filePath)207 Document *CuffmergeSupportTask::prepareDocument(const Workflow::SharedDbiDataHandler &annTableHandler, const QString &filePath) {
208 DocumentFormat *format = AppContext::getDocumentFormatRegistry()->getFormatById(BaseDocumentFormats::GTF);
209 SAFE_POINT_EXT(nullptr != format, setError(L10N::nullPointerError("GTF format")), nullptr);
210
211 IOAdapterFactory *iof = AppContext::getIOAdapterRegistry()->getIOAdapterFactoryById(BaseIOAdapters::LOCAL_FILE);
212 SAFE_POINT_EXT(nullptr != iof, setError(L10N::nullPointerError("I/O adapter factory")), nullptr);
213
214 AnnotationTableObject *annTable = Workflow::StorageUtils::getAnnotationTableObject(settings.storage, annTableHandler);
215 SAFE_POINT_EXT(nullptr != annTable, setError(L10N::nullPointerError("source annotation data")), nullptr);
216
217 Document *doc = format->createNewLoadedDocument(iof, filePath, stateInfo);
218 CHECK_OP(stateInfo, nullptr);
219 doc->setDocumentOwnsDbiResources(false);
220 doc->addObject(annTable);
221
222 return doc;
223 }
224
getOutputFiles() const225 QStringList CuffmergeSupportTask::getOutputFiles() const {
226 return outputFiles;
227 }
228
229 /************************************************************************/
230 /* CuffmergeSettings */
231 /************************************************************************/
CuffmergeSettings()232 CuffmergeSettings::CuffmergeSettings()
233 : minIsoformFraction(0.05),
234 storage(nullptr) {
235 }
236
237 } // namespace U2
238