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 "GenomeAlignerIndexWorker.h"
23 
24 #include <U2Core/Log.h>
25 
26 #include <U2Designer/DelegateEditors.h>
27 
28 #include <U2Gui/DialogUtils.h>
29 
30 #include <U2Lang/ActorPrototypeRegistry.h>
31 #include <U2Lang/BaseActorCategories.h>
32 #include <U2Lang/BaseAttributes.h>
33 #include <U2Lang/BasePorts.h>
34 #include <U2Lang/BaseSlots.h>
35 #include <U2Lang/BaseTypes.h>
36 #include <U2Lang/CoreLibConstants.h>
37 #include <U2Lang/IntegralBusModel.h>
38 #include <U2Lang/WorkflowEnv.h>
39 
40 #include "GenomeAlignerPlugin.h"
41 
42 namespace U2 {
43 namespace LocalWorkflow {
44 
45 static const QString INDEX_PORT_ID("in-gen-al-index");
46 static const QString INDEX_OUT_PORT_ID("out-gen-al-index");
47 static const QString INDEX_SLOT("index-slot");
48 
49 static const QString REFSEQ_URL_ATTR("url-reference");
50 static const QString INDEX_URL_ATTR("url-index");
51 static const QString REF_SIZE_ATTR("ref-size");
52 
53 const QString GenomeAlignerBuildWorkerFactory::ACTOR_ID("gen-al-build-index");
54 const QString GenomeAlignerIndexReaderWorkerFactory::ACTOR_ID("gen-al-read-index");
55 
56 /************************************************************************/
57 /* Genome aligner index build                                           */
58 /************************************************************************/
init()59 void GenomeAlignerBuildWorkerFactory::init() {
60     QList<PortDescriptor *> p;
61     QList<Attribute *> a;
62     Descriptor oud(INDEX_OUT_PORT_ID, QString("Genome aligner index"), QString("Result genome aligner index of reference sequence."));
63 
64     QMap<Descriptor, DataTypePtr> outM;
65     outM[INDEX_SLOT] = GenomeAlignerPlugin::GENOME_ALIGNER_INDEX_TYPE();
66     p << new PortDescriptor(oud, DataTypePtr(new MapDataType("gen.al.build.index.out", outM)), false /*input*/, true /*multi*/);
67 
68     Descriptor refseq(REFSEQ_URL_ATTR, GenomeAlignerBuildWorker::tr("Reference"), GenomeAlignerBuildWorker::tr("Reference sequence url. The short reads will be aligned to this reference genome."));
69     Descriptor desc(ACTOR_ID, GenomeAlignerBuildWorker::tr("Genome aligner index builder"), GenomeAlignerBuildWorker::tr("GenomeAlignerBuild builds an index from a set of DNA sequences. GenomeAlignerBuild outputs a set of 3 files with suffixes .idx, .ref, .sarr. These files together constitute the index: they are all that is needed to align reads to that reference."));
70     Descriptor index(INDEX_URL_ATTR, GenomeAlignerBuildWorker::tr("Index"), GenomeAlignerBuildWorker::tr("Output index url."));
71     Descriptor refSize(REF_SIZE_ATTR, GenomeAlignerBuildWorker::tr("Reference fragmentation"), GenomeAlignerBuildWorker::tr("Reference fragmentation size"));
72 
73     a << new Attribute(refseq, BaseTypes::STRING_TYPE(), true /*required*/, QString());
74     a << new Attribute(index, BaseTypes::STRING_TYPE(), true /*required*/, QString());
75     a << new Attribute(refSize, BaseTypes::NUM_TYPE(), true /*required*/, 10);
76 
77     ActorPrototype *proto = new IntegralBusActorPrototype(desc, p, a);
78 
79     QMap<QString, PropertyDelegate *> delegates;
80 
81     delegates[REFSEQ_URL_ATTR] = new URLDelegate(DialogUtils::prepareDocumentsFileFilter(true), QString(), true);
82     delegates[INDEX_URL_ATTR] = new URLDelegate(DialogUtils::prepareDocumentsFileFilter(true), QString(), false);
83 
84     proto->setEditor(new DelegateEditor(delegates));
85     proto->setPrompter(new GenomeAlignerBuildPrompter());
86     proto->setIconPath(":core/images/align.png");
87     WorkflowEnv::getProtoRegistry()->registerProto(BaseActorCategories::CATEGORY_ASSEMBLY(), proto);
88 
89     DomainFactory *localDomain = WorkflowEnv::getDomainRegistry()->getById(LocalDomainFactory::ID);
90     localDomain->registerEntry(new GenomeAlignerBuildWorkerFactory());
91 }
92 
init()93 void GenomeAlignerBuildWorker::init() {
94     output = ports.value(INDEX_OUT_PORT_ID);
95     refSeqUrl = actor->getParameter(REFSEQ_URL_ATTR)->getAttributeValue<QString>(context);
96     indexUrl = actor->getParameter(INDEX_URL_ATTR)->getAttributeValue<QString>(context);
97 
98     settings.prebuiltIndex = false;
99 }
100 
isReady() const101 bool GenomeAlignerBuildWorker::isReady() const {
102     return !isDone();
103 }
104 
tick()105 Task *GenomeAlignerBuildWorker::tick() {
106     if (refSeqUrl.isEmpty()) {
107         algoLog.trace(GenomeAlignerBuildWorker::tr("Reference sequence URL is empty"));
108         return nullptr;
109     }
110     if (indexUrl.isEmpty()) {
111         algoLog.trace(GenomeAlignerBuildWorker::tr("Result index URL is empty"));
112         return nullptr;
113     }
114 
115     settings.refSeqUrl = refSeqUrl;
116     settings.indexFileName = indexUrl.getURLString();
117     Task *t = new GenomeAlignerTask(settings, true);
118     connect(t, SIGNAL(si_stateChanged()), SLOT(sl_taskFinished()));
119     return t;
120 }
121 
sl_taskFinished()122 void GenomeAlignerBuildWorker::sl_taskFinished() {
123     GenomeAlignerTask *t = qobject_cast<GenomeAlignerTask *>(sender());
124     if (t->getState() != Task::State_Finished) {
125         return;
126     }
127 
128     done = true;
129 
130     QVariant v = qVariantFromValue<QString>(t->getIndexPath());
131     output->put(Message(GenomeAlignerPlugin::GENOME_ALIGNER_INDEX_TYPE(), v));
132     output->setEnded();
133     algoLog.trace(tr("Genome aligner index building finished. Result name is %1").arg(t->getIndexPath()));
134 }
135 
isDone() const136 bool GenomeAlignerBuildWorker::isDone() const {
137     return done;
138 }
139 
cleanup()140 void GenomeAlignerBuildWorker::cleanup() {
141 }
142 
composeRichDoc()143 QString GenomeAlignerBuildPrompter::composeRichDoc() {
144     QString refSeqUrl = getParameter(REFSEQ_URL_ATTR).toString();
145     QString refSeq = (refSeqUrl.isEmpty() ? "" : QString("<u>%1</u>").arg(GUrl(refSeqUrl).fileName()));
146 
147     QString doc = tr("Build genome aligner index from %1 and send it url to output.").arg(refSeq);
148 
149     return doc;
150 }
151 
152 /************************************************************************/
153 /* Genome aligner index read                                            */
154 /************************************************************************/
init()155 void GenomeAlignerIndexReaderWorkerFactory::init() {
156     QList<PortDescriptor *> p;
157     QList<Attribute *> a;
158     Descriptor oud(INDEX_OUT_PORT_ID, GenomeAlignerIndexReaderWorker::tr("Genome aligner index"), GenomeAlignerIndexReaderWorker::tr("Result of genome aligner index builder."));
159 
160     QMap<Descriptor, DataTypePtr> outM;
161     outM[INDEX_SLOT] = GenomeAlignerPlugin::GENOME_ALIGNER_INDEX_TYPE();
162     p << new PortDescriptor(oud, DataTypePtr(new MapDataType("gen.al.index.reader.out", outM)), false /*input*/, true /*multi*/);
163 
164     Descriptor desc(ACTOR_ID, GenomeAlignerIndexReaderWorker::tr("Genome aligner index reader"), GenomeAlignerIndexReaderWorker::tr("Read a set of several files with extensions .idx, .ref, .X.sarr. These files together constitute the index: they are all that is needed to align reads to that reference."));
165     Descriptor index(INDEX_URL_ATTR, GenomeAlignerIndexReaderWorker::tr("Index"), GenomeAlignerIndexReaderWorker::tr("Select an index file with the .idx extension"));
166 
167     a << new Attribute(index, BaseTypes::STRING_TYPE(), true /*required*/, QString());
168 
169     ActorPrototype *proto = new IntegralBusActorPrototype(desc, p, a);
170 
171     QMap<QString, PropertyDelegate *> delegates;
172 
173     delegates[INDEX_URL_ATTR] = new URLDelegate(DialogUtils::prepareDocumentsFileFilter(true), QString(), false, false, false);
174 
175     proto->setEditor(new DelegateEditor(delegates));
176     proto->setPrompter(new GenomeAlignerIndexReaderPrompter());
177     proto->setIconPath(":core/images/align.png");
178     WorkflowEnv::getProtoRegistry()->registerProto(BaseActorCategories::CATEGORY_ASSEMBLY(), proto);
179 
180     DomainFactory *localDomain = WorkflowEnv::getDomainRegistry()->getById(LocalDomainFactory::ID);
181     localDomain->registerEntry(new GenomeAlignerIndexReaderWorkerFactory());
182 }
183 
init()184 void GenomeAlignerIndexReaderWorker::init() {
185     output = ports.value(INDEX_OUT_PORT_ID);
186     indexUrl = actor->getParameter(INDEX_URL_ATTR)->getAttributeValue<QString>(context);
187 }
188 
isReady() const189 bool GenomeAlignerIndexReaderWorker::isReady() const {
190     return !isDone();
191 }
192 
tick()193 Task *GenomeAlignerIndexReaderWorker::tick() {
194     if (indexUrl.isEmpty()) {
195         algoLog.trace(GenomeAlignerIndexReaderWorker::tr("Index URL is empty"));
196         return nullptr;
197     }
198     Task *t = new Task("Genome aligner index reader", TaskFlags_NR_FOSCOE);
199     connect(t, SIGNAL(si_stateChanged()), SLOT(sl_taskFinished()));
200     return t;
201 }
202 
sl_taskFinished()203 void GenomeAlignerIndexReaderWorker::sl_taskFinished() {
204     QVariant v = qVariantFromValue<QString>(indexUrl.getURLString());
205     output->put(Message(GenomeAlignerPlugin::GENOME_ALIGNER_INDEX_TYPE(), v));
206     output->setEnded();
207     done = true;
208     algoLog.trace(tr("Reading genome aligner index finished. Result name is %1").arg(indexUrl.getURLString()));
209 }
210 
isDone() const211 bool GenomeAlignerIndexReaderWorker::isDone() const {
212     return done;
213 }
214 
cleanup()215 void GenomeAlignerIndexReaderWorker::cleanup() {
216 }
217 
composeRichDoc()218 QString GenomeAlignerIndexReaderPrompter::composeRichDoc() {
219     QString indexUrl = getParameter(INDEX_URL_ATTR).toString();
220     QString index = (indexUrl.isEmpty() ? "" : QString("<u>%1</u>").arg(GUrl(indexUrl).fileName()));
221 
222     QString doc = tr("Read genome aligner index from %1 and send it url to output.").arg(index);
223 
224     return doc;
225 }
226 }  // namespace LocalWorkflow
227 }  // namespace U2
228