1 /* $Id: data_manager.cpp 123357 2008-04-01 19:42:38Z thiessen $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Authors: Paul Thiessen
27 *
28 * File Description:
29 * class to manage different root ASN data types
30 *
31 * ===========================================================================
32 */
33
34 #include <ncbi_pch.hpp>
35 #include <corelib/ncbistd.hpp>
36 #include <serial/iterator.hpp>
37
38 #include <objects/ncbimime/Entrez_general.hpp>
39 #include <objects/ncbimime/Biostruc_align.hpp>
40 #include <objects/ncbimime/Biostruc_align_seq.hpp>
41 #include <objects/ncbimime/Biostruc_seq.hpp>
42 #include <objects/ncbimime/Biostruc_seqs.hpp>
43 #include <objects/ncbimime/Biostruc_seqs_aligns_cdd.hpp>
44 #include <objects/ncbimime/Bundle_seqs_aligns.hpp>
45 #include <objects/seqset/Bioseq_set.hpp>
46 #include <objects/mmdb3/Biostruc_feature_set.hpp>
47 #include <objects/cdd/Cdd_descr_set.hpp>
48 #include <objects/cdd/Cdd_descr.hpp>
49 #include <objects/cdd/Cdd_id.hpp>
50 #include <objects/cdd/Global_id.hpp>
51 #include <objects/cdd/Cdd_id_set.hpp>
52 #include <objects/seqalign/seqalign__.hpp>
53 #include <objects/general/Object_id.hpp>
54
55 #include "remove_header_conflicts.hpp"
56
57 #include "asn_reader.hpp"
58 #include "data_manager.hpp"
59 #include "structure_set.hpp"
60 #include "sequence_set.hpp"
61 #include "alignment_set.hpp"
62 #include "cn3d_tools.hpp"
63
64 #include <algo/structure/cd_utils/cuCD.hpp>
65
66 USING_NCBI_SCOPE;
67 USING_SCOPE(objects);
68
69
BEGIN_SCOPE(Cn3D)70 BEGIN_SCOPE(Cn3D)
71
72 ASNDataManager::ASNDataManager(ncbi::objects::CNcbi_mime_asn1 *mime)
73 {
74 mimeData.Reset(mime);
75 Load();
76 }
77
ASNDataManager(ncbi::objects::CCdd * cdd)78 ASNDataManager::ASNDataManager(ncbi::objects::CCdd *cdd)
79 {
80 cddData.Reset(cdd);
81 Load();
82 }
83
~ASNDataManager(void)84 ASNDataManager::~ASNDataManager(void)
85 {
86 }
87
Load(void)88 void ASNDataManager::Load(void)
89 {
90 // initialization
91 seqEntryList = NULL;
92 masterBiostruc = NULL;
93 biostrucList = NULL;
94 biostrucModelType = eModel_type_ncbi_all_atom; // default, for CDD's
95 sequenceAlignments = NULL;
96 structureAlignments = NULL;
97 bundleImports = NULL;
98 cddUpdates = NULL;
99 dataChanged = 0;
100
101 // remove consensus sequence, then do a check over the whole tree to make sure any reference to it is gone
102 if (GetInternalCDDData()) {
103 RemoveConsensusFromCDD();
104 for (CTypeConstIterator < CSeq_id > i(ConstBegin(*(GetInternalCDDData()))); i; ++i) {
105 if (i->IsLocal() && i->GetLocal().IsStr() && i->GetLocal().GetStr() == "consensus") {
106 WARNINGMSG("ASNDataManager::Load() - consensus still referenced in the data: " << i.GetContext());
107 break;
108 }
109 }
110 } else if (mimeData.NotEmpty()) {
111 for (CTypeConstIterator < CSeq_id > i(ConstBegin(mimeData.GetObject())); i; ++i) {
112 if (i->IsLocal() && i->GetLocal().IsStr() && i->GetLocal().GetStr() == "consensus") {
113 WARNINGMSG("ASNDataManager::Load() - a consensus is present in the data: " << i.GetContext());
114 break;
115 }
116 }
117 }
118
119 // mime
120 if (mimeData.NotEmpty()) {
121 if (mimeData->IsEntrez()) {
122 if (mimeData->GetEntrez().GetData().IsStructure())
123 masterBiostruc = &(mimeData->SetEntrez().SetData().SetStructure());
124 }
125
126 else if (mimeData->IsAlignstruc()) {
127 seqEntryList = &(mimeData->SetAlignstruc().SetSequences());
128 masterBiostruc = &(mimeData->SetAlignstruc().SetMaster());
129 biostrucList = &(mimeData->SetAlignstruc().SetSlaves());
130 structureAlignments = &(mimeData->SetAlignstruc().SetAlignments());
131 sequenceAlignments = &(mimeData->SetAlignstruc().SetSeqalign());
132 }
133
134 else if (mimeData->IsAlignseq()) {
135 seqEntryList = &(mimeData->SetAlignseq().SetSequences());
136 sequenceAlignments = &(mimeData->SetAlignseq().SetSeqalign());
137 }
138
139 else if (mimeData->IsStrucseq()) {
140 seqEntryList = &(mimeData->SetStrucseq().SetSequences());
141 masterBiostruc = &(mimeData->SetStrucseq().SetStructure());
142 }
143
144 else if (mimeData->IsStrucseqs()) {
145 seqEntryList = &(mimeData->SetStrucseqs().SetSequences());
146 masterBiostruc = &(mimeData->SetStrucseqs().SetStructure());
147 sequenceAlignments = &(mimeData->SetStrucseqs().SetSeqalign());
148 }
149
150 else if (mimeData->IsGeneral()) {
151 if (mimeData->GetGeneral().IsSetStructures())
152 biostrucList = &(mimeData->SetGeneral().SetStructures());
153
154 if (mimeData->GetGeneral().IsSetStructure_type())
155 // assume structure-type values match MMDB's Model-type
156 biostrucModelType = (EModel_type) mimeData->GetGeneral().GetStructure_type();
157
158 if (mimeData->GetGeneral().GetSeq_align_data().IsBundle()) {
159 if (mimeData->GetGeneral().GetSeq_align_data().GetBundle().IsSetSequences())
160 seqEntryList = &(mimeData->SetGeneral().SetSeq_align_data().SetBundle().SetSequences());
161 if (mimeData->GetGeneral().GetSeq_align_data().GetBundle().IsSetStrucaligns())
162 structureAlignments =
163 &(mimeData->SetGeneral().SetSeq_align_data().SetBundle().SetStrucaligns());
164 if (mimeData->GetGeneral().GetSeq_align_data().GetBundle().IsSetSeqaligns())
165 sequenceAlignments =
166 &(mimeData->SetGeneral().SetSeq_align_data().SetBundle().SetSeqaligns());
167 if (mimeData->GetGeneral().GetSeq_align_data().GetBundle().IsSetImports()) {
168 bundleImports = &(mimeData->SetGeneral().SetSeq_align_data().SetBundle().SetImports());
169 // make "fake" Update-aligns from imports (to pass to alignment manager)
170 SeqAnnotList::iterator i,
171 ie = mimeData->SetGeneral().SetSeq_align_data().SetBundle().SetImports().end();
172 for (i=mimeData->SetGeneral().SetSeq_align_data().SetBundle().SetImports().begin();
173 i!= ie; ++i) {
174 CRef < CUpdate_align > update(new CUpdate_align());
175 update->SetSeqannot(**i);
176 update->SetType(CUpdate_align::eType_other);
177 bundleImportsFaked.push_back(update);
178 }
179 }
180 }
181
182 else { // cdd
183 if (mimeData->GetGeneral().GetSeq_align_data().GetCdd().IsSetSequences()) {
184 if (mimeData->GetGeneral().GetSeq_align_data().GetCdd().GetSequences().IsSeq()) {
185 // convert Seq-entry type from seq to set
186 CRef < CSeq_entry > seqEntry(
187 &(mimeData->SetGeneral().SetSeq_align_data().SetCdd().SetSequences()));
188 mimeData->SetGeneral().SetSeq_align_data().SetCdd().ResetSequences();
189 mimeData->SetGeneral().SetSeq_align_data().SetCdd().SetSequences().
190 SetSet().SetSeq_set().push_back(seqEntry);
191 }
192 seqEntryList =
193 &(mimeData->SetGeneral().SetSeq_align_data().SetCdd().SetSequences().SetSet().SetSeq_set());
194 }
195 if (mimeData->GetGeneral().GetSeq_align_data().GetCdd().IsSetFeatures())
196 structureAlignments = &(mimeData->SetGeneral().SetSeq_align_data().SetCdd().SetFeatures());
197 if (mimeData->GetGeneral().GetSeq_align_data().GetCdd().IsSetSeqannot())
198 sequenceAlignments = &(mimeData->SetGeneral().SetSeq_align_data().SetCdd().SetSeqannot());
199 if (mimeData->GetGeneral().GetSeq_align_data().GetCdd().IsSetPending())
200 cddUpdates = &(mimeData->SetGeneral().SetSeq_align_data().SetCdd().SetPending());
201 }
202 }
203
204 else
205 ERRORMSG("Unrecognized mime type!");
206 }
207
208 // CDD
209 else {
210 if (cddData->IsSetSequences()) {
211 if (cddData->GetSequences().IsSeq()) {
212 // convert Seq-entry type from seq to set
213 CRef < CSeq_entry > seqEntry(&(cddData->SetSequences()));
214 cddData->ResetSequences();
215 cddData->SetSequences().SetSet().SetSeq_set().push_back(seqEntry);
216 }
217 seqEntryList = &(cddData->SetSequences().SetSet().SetSeq_set());
218 }
219 if (cddData->IsSetFeatures())
220 structureAlignments = &(cddData->SetFeatures());
221 if (cddData->IsSetSeqannot())
222 sequenceAlignments = &(cddData->SetSeqannot());
223 if (cddData->IsSetPending())
224 cddUpdates = &(cddData->SetPending());
225 }
226
227 // sequence list is interpreted differently for single structure
228 isSingleStructure = (mimeData.NotEmpty() &&
229 (mimeData->IsStrucseq() ||
230 (mimeData->IsGeneral() &&
231 !sequenceAlignments && !structureAlignments &&
232 biostrucList && biostrucList->size() == 1)));
233 TRACEMSG("is single structure: " << (isSingleStructure ? "yes" : "no"));
234
235 // pre-screen sequence alignments to make sure they're all a type we can deal with
236 if (sequenceAlignments) {
237 list < CRef < CSeq_align > > validAlignments;
238 SeqAnnotList::const_iterator n, ne = sequenceAlignments->end();
239 for (n=sequenceAlignments->begin(); n!=ne; ++n) {
240
241 if (!n->GetObject().GetData().IsAlign()) {
242 ERRORMSG("Warning - confused by seqannot data format");
243 continue;
244 }
245 if (n != sequenceAlignments->begin()) TRACEMSG("multiple Seq-annots");
246
247 CSeq_annot::C_Data::TAlign::const_iterator
248 a, ae = n->GetObject().GetData().GetAlign().end();
249 for (a=n->GetObject().GetData().GetAlign().begin(); a!=ae; ++a) {
250
251 // verify this is a type of alignment we can deal with
252 if (!(a->GetObject().GetType() != CSeq_align::eType_partial ||
253 a->GetObject().GetType() != CSeq_align::eType_diags) ||
254 !a->GetObject().IsSetDim() || a->GetObject().GetDim() != 2 ||
255 (!a->GetObject().GetSegs().IsDendiag() && !a->GetObject().GetSegs().IsDenseg())) {
256 ERRORMSG("Warning - confused by alignment type");
257 continue;
258 }
259 validAlignments.push_back(*a);
260 }
261 }
262
263 sequenceAlignments->clear();
264 if (validAlignments.size() == 0) {
265 ERRORMSG("Warning - no valid Seq-aligns present");
266 sequenceAlignments = NULL;
267 } else {
268 sequenceAlignments->push_back(CRef < CSeq_annot > (new CSeq_annot()));
269 // copy list of valid alignments only
270 sequenceAlignments->front()->SetData().SetAlign() = validAlignments;
271 }
272 }
273 }
274
RemoveConsensusFromCDD(void)275 void ASNDataManager::RemoveConsensusFromCDD(void)
276 {
277 CCdd *cdd = GetInternalCDDData();
278 if (!cdd)
279 return;
280
281 int result = cd_utils::PurgeConsensusSequences((cd_utils::CCdCore *) cdd, true);
282 TRACEMSG("PurgeConsensusSequences() removed " << result << " sequence(s)");
283 // string err;
284 // WriteASNToFile("Cdd.txt", *cdd, false, &err);
285 }
286
ConvertMimeDataToCDD(const std::string & cddName)287 bool ASNDataManager::ConvertMimeDataToCDD(const std::string& cddName)
288 {
289 // if we have CDD data already, this is really easy
290 if (IsCDDInMime()) {
291 cddData.Reset(GetInternalCDDData());
292 }
293 else if (IsCDD()){
294 return true; // nothing to do
295 }
296
297 // otherwise, splice together from mime data
298 else {
299 CRef < CCdd > cdd(new CCdd());
300 cdd->SetName(cddName);
301
302 // make up a local id
303 static int localID = 1;
304 CRef < CCdd_id > id(new CCdd_id());
305 cdd->SetId().Set().push_back(id);
306 CNcbiOstrstream oss;
307 oss << "loc_" << localID++;
308 id->SetGid().SetAccession((string) CNcbiOstrstreamToString(oss));
309
310 // fill in data
311 if (!seqEntryList) {
312 ERRORMSG("can't find sequences to put into new Cdd");
313 return false;
314 }
315 cdd->SetSequences().SetSet().SetSeq_set() = *seqEntryList;
316 if (!sequenceAlignments) {
317 ERRORMSG("can't find sequence alignments to put into new Cdd");
318 return false;
319 }
320 cdd->SetSeqannot() = *sequenceAlignments;
321 if (structureAlignments)
322 cdd->SetFeatures(*structureAlignments);
323 if (cddUpdates)
324 cdd->SetPending() = *cddUpdates;
325 if (bundleImportsFaked.size() > 0)
326 cdd->SetPending().splice(cdd->SetPending().end(), bundleImportsFaked);
327
328 cddData.Reset(cdd.GetPointer());
329 }
330
331 mimeData.Reset();
332 Load();
333 return true;
334 }
335
GetOrCreateSequenceAlignments(void)336 ASNDataManager::SeqAnnotList * ASNDataManager::GetOrCreateSequenceAlignments(void)
337 {
338 // if necessary, convert mime data into general type that has a place for alignments
339 if (!sequenceAlignments && mimeData.NotEmpty() && !mimeData->IsGeneral())
340 ConvertMimeToGeneral();
341
342 if (!sequenceAlignments && mimeData.NotEmpty() && mimeData->IsGeneral() &&
343 mimeData->GetGeneral().GetSeq_align_data().IsBundle())
344 sequenceAlignments =
345 &(mimeData->SetGeneral().SetSeq_align_data().SetBundle().SetSeqaligns());
346 return sequenceAlignments;
347 }
348
GetStyleDictionary(void) const349 const CCn3d_style_dictionary * ASNDataManager::GetStyleDictionary(void) const
350 {
351 if (mimeData.NotEmpty()) {
352 if (mimeData->IsAlignstruc() && mimeData->GetAlignstruc().IsSetStyle_dictionary())
353 return &(mimeData->GetAlignstruc().GetStyle_dictionary());
354 else if (mimeData->IsAlignseq() && mimeData->GetAlignseq().IsSetStyle_dictionary())
355 return &(mimeData->GetAlignseq().GetStyle_dictionary());
356 else if (mimeData->IsStrucseq() && mimeData->GetStrucseq().IsSetStyle_dictionary())
357 return &(mimeData->GetStrucseq().GetStyle_dictionary());
358 else if (mimeData->IsStrucseqs() && mimeData->GetStrucseqs().IsSetStyle_dictionary())
359 return &(mimeData->GetStrucseqs().GetStyle_dictionary());
360 else if (mimeData->IsGeneral()) {
361 if (mimeData->GetGeneral().GetSeq_align_data().IsBundle() &&
362 mimeData->GetGeneral().GetSeq_align_data().GetBundle().IsSetStyle_dictionary())
363 return &(mimeData->GetGeneral().GetSeq_align_data().GetBundle().GetStyle_dictionary());
364 else if (mimeData->GetGeneral().GetSeq_align_data().IsCdd() &&
365 mimeData->GetGeneral().GetSeq_align_data().GetCdd().IsSetStyle_dictionary())
366 return &(mimeData->GetGeneral().GetSeq_align_data().GetCdd().GetStyle_dictionary());
367 }
368 } else if (cddData->IsSetStyle_dictionary())
369 return &(cddData->GetStyle_dictionary());
370
371 return NULL;
372 }
373
SetStyleDictionary(ncbi::objects::CCn3d_style_dictionary & styles)374 void ASNDataManager::SetStyleDictionary(ncbi::objects::CCn3d_style_dictionary& styles)
375 {
376 if (mimeData.NotEmpty()) {
377 if (mimeData->IsAlignstruc()) mimeData->SetAlignstruc().SetStyle_dictionary(styles);
378 else if (mimeData->IsAlignseq()) mimeData->SetAlignseq().SetStyle_dictionary(styles);
379 else if (mimeData->IsStrucseq()) mimeData->SetStrucseq().SetStyle_dictionary(styles);
380 else if (mimeData->IsStrucseqs()) mimeData->SetStrucseqs().SetStyle_dictionary(styles);
381 else if (mimeData->IsGeneral()) {
382 if (mimeData->GetGeneral().GetSeq_align_data().IsBundle())
383 mimeData->SetGeneral().SetSeq_align_data().SetBundle().SetStyle_dictionary(styles);
384 else
385 mimeData->SetGeneral().SetSeq_align_data().SetCdd().SetStyle_dictionary(styles);
386 }
387 } else
388 cddData->SetStyle_dictionary(styles);
389 }
390
RemoveStyleDictionary(void)391 void ASNDataManager::RemoveStyleDictionary(void)
392 {
393 if (mimeData.NotEmpty()) {
394 if (mimeData->IsAlignstruc()) mimeData->SetAlignstruc().ResetStyle_dictionary();
395 else if (mimeData->IsAlignseq()) mimeData->SetAlignseq().ResetStyle_dictionary();
396 else if (mimeData->IsStrucseq()) mimeData->SetStrucseq().ResetStyle_dictionary();
397 else if (mimeData->IsStrucseqs()) mimeData->SetStrucseqs().ResetStyle_dictionary();
398 else if (mimeData->IsGeneral()) {
399 if (mimeData->GetGeneral().GetSeq_align_data().IsBundle())
400 mimeData->SetGeneral().SetSeq_align_data().SetBundle().ResetStyle_dictionary();
401 else
402 mimeData->SetGeneral().SetSeq_align_data().SetCdd().ResetStyle_dictionary();
403 }
404 } else
405 cddData->ResetStyle_dictionary();
406 }
407
GetUserAnnotations(void) const408 const CCn3d_user_annotations * ASNDataManager::GetUserAnnotations(void) const
409 {
410 if (mimeData.NotEmpty()) {
411 if (mimeData->IsAlignstruc() && mimeData->GetAlignstruc().IsSetUser_annotations())
412 return &(mimeData->GetAlignstruc().GetUser_annotations());
413 else if (mimeData->IsAlignseq() && mimeData->GetAlignseq().IsSetUser_annotations())
414 return &(mimeData->GetAlignseq().GetUser_annotations());
415 else if (mimeData->IsStrucseq() && mimeData->GetStrucseq().IsSetUser_annotations())
416 return &(mimeData->GetStrucseq().GetUser_annotations());
417 else if (mimeData->IsStrucseqs() && mimeData->GetStrucseqs().IsSetUser_annotations())
418 return &(mimeData->GetStrucseqs().GetUser_annotations());
419 else if (mimeData->IsGeneral()) {
420 if (mimeData->GetGeneral().GetSeq_align_data().IsBundle() &&
421 mimeData->GetGeneral().GetSeq_align_data().GetBundle().IsSetUser_annotations())
422 return &(mimeData->GetGeneral().GetSeq_align_data().GetBundle().GetUser_annotations());
423 else if (mimeData->GetGeneral().GetSeq_align_data().IsCdd() &&
424 mimeData->GetGeneral().GetSeq_align_data().GetCdd().IsSetUser_annotations())
425 return &(mimeData->GetGeneral().GetSeq_align_data().GetCdd().GetUser_annotations());
426 }
427 } else if (cddData->IsSetUser_annotations())
428 return &(cddData->GetUser_annotations());
429
430 return NULL;
431 }
432
SetUserAnnotations(ncbi::objects::CCn3d_user_annotations & annots)433 void ASNDataManager::SetUserAnnotations(ncbi::objects::CCn3d_user_annotations& annots)
434 {
435 if (mimeData.NotEmpty()) {
436 if (mimeData->IsAlignstruc()) mimeData->SetAlignstruc().SetUser_annotations(annots);
437 else if (mimeData->IsAlignseq()) mimeData->SetAlignseq().SetUser_annotations(annots);
438 else if (mimeData->IsStrucseq()) mimeData->SetStrucseq().SetUser_annotations(annots);
439 else if (mimeData->IsStrucseqs()) mimeData->SetStrucseqs().SetUser_annotations(annots);
440 else if (mimeData->IsGeneral()) {
441 if (mimeData->GetGeneral().GetSeq_align_data().IsBundle())
442 mimeData->SetGeneral().SetSeq_align_data().SetBundle().SetUser_annotations(annots);
443 else
444 mimeData->SetGeneral().SetSeq_align_data().SetCdd().SetUser_annotations(annots);
445 }
446 } else
447 cddData->SetUser_annotations(annots);
448 }
449
RemoveUserAnnotations(void)450 void ASNDataManager::RemoveUserAnnotations(void)
451 {
452 if (mimeData.NotEmpty()) {
453 if (mimeData->IsAlignstruc()) mimeData->SetAlignstruc().ResetUser_annotations();
454 else if (mimeData->IsAlignseq()) mimeData->SetAlignseq().ResetUser_annotations();
455 else if (mimeData->IsStrucseq()) mimeData->SetStrucseq().ResetUser_annotations();
456 else if (mimeData->IsStrucseqs()) mimeData->SetStrucseqs().ResetUser_annotations();
457 else if (mimeData->IsGeneral()) {
458 if (mimeData->GetGeneral().GetSeq_align_data().IsBundle())
459 mimeData->SetGeneral().SetSeq_align_data().SetBundle().ResetUser_annotations();
460 else
461 mimeData->SetGeneral().SetSeq_align_data().SetCdd().ResetUser_annotations();
462 }
463 } else
464 cddData->ResetUser_annotations();
465 }
466
SetStructureAlignments(ncbi::objects::CBiostruc_annot_set * strucAligns)467 void ASNDataManager::SetStructureAlignments(ncbi::objects::CBiostruc_annot_set *strucAligns)
468 {
469 if (mimeData.NotEmpty() && mimeData->IsGeneral() && mimeData->GetGeneral().GetSeq_align_data().IsBundle()) {
470 if (strucAligns)
471 mimeData->SetGeneral().SetSeq_align_data().SetBundle().SetStrucaligns(*strucAligns);
472 else
473 mimeData->SetGeneral().SetSeq_align_data().SetBundle().ResetStrucaligns();
474 } else if (GetInternalCDDData()) {
475 if (strucAligns)
476 GetInternalCDDData()->SetFeatures(*strucAligns);
477 else
478 GetInternalCDDData()->ResetFeatures();
479 } else
480 ERRORMSG("ASNDataManager::SetStructureAlignments() - can't add to this data type");
481 structureAlignments = strucAligns;
482 }
483
AddBiostrucToASN(ncbi::objects::CBiostruc * biostruc)484 bool ASNDataManager::AddBiostrucToASN(ncbi::objects::CBiostruc *biostruc)
485 {
486 // if can't store add'l Biostrucs currently, try to convert to general mime if possible
487 if (!biostrucList && mimeData.NotEmpty() && !mimeData->IsGeneral())
488 ConvertMimeToGeneral();
489
490 // add structure to list if there is one
491 if (biostrucList) {
492 biostrucList->push_back(CRef<CBiostruc>(biostruc));
493 return true;
494 }
495
496 // if this is a CDD, we never store Biostrucs; but return true to pretend success
497 if (IsCDD()) return true;
498
499 return false;
500 }
501
ConvertMimeToGeneral(void)502 bool ASNDataManager::ConvertMimeToGeneral(void)
503 {
504 if (mimeData.Empty() || mimeData->IsGeneral()) {
505 ERRORMSG("ASNDataManager::ConvertMimeToGeneral() - can't convert to general mime type");
506 return false;
507 }
508
509 CNcbi_mime_asn1 *newMime = new CNcbi_mime_asn1();
510
511 // copy structures
512 if (biostrucList)
513 newMime->SetGeneral().SetStructures() = *biostrucList; // copy list
514 if (masterBiostruc) {
515 newMime->SetGeneral().SetStructures().push_front(CRef<CBiostruc>(masterBiostruc));
516 masterBiostruc = NULL;
517 }
518 biostrucList = (newMime->GetGeneral().GetStructures().size() > 0) ?
519 &(newMime->SetGeneral().SetStructures()) : NULL;
520
521 // copy alignment data into bundle
522 CBundle_seqs_aligns *bundle = new CBundle_seqs_aligns();
523 newMime->SetGeneral().SetSeq_align_data().SetBundle(*bundle);
524 if (seqEntryList) {
525 bundle->SetSequences() = *seqEntryList;
526 seqEntryList = &(bundle->SetSequences());
527 }
528 if (structureAlignments)
529 bundle->SetStrucaligns(*structureAlignments);
530 if (sequenceAlignments) {
531 bundle->SetSeqaligns() = *sequenceAlignments;
532 sequenceAlignments = &(bundle->SetSeqaligns());
533 }
534
535 // install new root mime structure
536 mimeData.Reset(newMime);
537 SetDataChanged(StructureSet::eOtherData);
538 return true;
539 }
540
ReplaceUpdates(UpdateAlignList & newUpdates)541 void ASNDataManager::ReplaceUpdates(UpdateAlignList& newUpdates)
542 {
543 // if necessary, convert mime data into general type that has a place for imports
544 if (mimeData.NotEmpty() && !mimeData->IsGeneral() && newUpdates.size() > 0)
545 ConvertMimeToGeneral();
546
547 // store new updates in asn data
548 if (mimeData.NotEmpty() && mimeData->IsGeneral()) {
549 if (mimeData->GetGeneral().GetSeq_align_data().IsCdd()) {
550 cddUpdates = &(mimeData->SetGeneral().SetSeq_align_data().SetCdd().SetPending());
551 *cddUpdates = newUpdates;
552 } else {
553 bundleImportsFaked = newUpdates;
554 // convert to plain imports to store in mime data (some data loss...)
555 bundleImports = &(mimeData->SetGeneral().SetSeq_align_data().SetBundle().SetImports());
556 bundleImports->clear();
557 UpdateAlignList::iterator u, ue = newUpdates.end();
558 for (u=newUpdates.begin(); u!=ue; ++u)
559 if ((*u)->IsSetSeqannot())
560 bundleImports->push_back(CRef < CSeq_annot > (&((*u)->SetSeqannot())));
561 }
562 } else if (cddData.NotEmpty()) {
563 cddUpdates = &(cddData->SetPending());
564 *cddUpdates = newUpdates;
565 } else if (newUpdates.size() > 0)
566 ERRORMSG("ASNDataManager::ReplaceUpdates() - can't put updates in this data type");
567
568 SetDataChanged(StructureSet::eUpdateData);
569 }
570
RemoveUnusedSequences(const AlignmentSet * alignmentSet,const SequenceList & updateSequences)571 void ASNDataManager::RemoveUnusedSequences(const AlignmentSet *alignmentSet,
572 const SequenceList& updateSequences)
573 {
574 if (!alignmentSet) return; // don't do this for single structures
575
576 if (!seqEntryList) {
577 ERRORMSG("ASNDataManager::RemoveUnusedSequences() - can't find sequence list");
578 return;
579 }
580
581 // update the asn sequences, keeping only those used in the multiple alignment and updates
582 seqEntryList->clear();
583 map < const MoleculeIdentifier *, bool > usedSeqs;
584 int nStructuredDependents = 0;
585
586 // macro to add the sequence to the list if not already present
587 #define CONDITIONAL_ADD_SEQENTRY(seq) do { \
588 if (usedSeqs.find((seq)->identifier) == usedSeqs.end()) { \
589 seqEntryList->resize(seqEntryList->size() + 1); \
590 seqEntryList->back().Reset(new CSeq_entry); \
591 seqEntryList->back().GetObject().SetSeq((const_cast<Sequence*>(seq))->bioseqASN.GetObject()); \
592 usedSeqs[(seq)->identifier] = true; \
593 } } while (0)
594
595 // always add master first
596 CONDITIONAL_ADD_SEQENTRY(alignmentSet->master);
597 // add from alignmentSet dependents
598 AlignmentSet::AlignmentList::const_iterator a, ae = alignmentSet->alignments.end();
599 for (a=alignmentSet->alignments.begin(); a!=ae; ++a) {
600 CONDITIONAL_ADD_SEQENTRY((*a)->dependent);
601 if ((*a)->dependent->molecule) ++nStructuredDependents;
602 }
603
604 // add from updates
605 SequenceList::const_iterator s, se = updateSequences.end();
606 for (s=updateSequences.begin(); s!=se; ++s)
607 CONDITIONAL_ADD_SEQENTRY((*s));
608
609 SetDataChanged(StructureSet::eSequenceData);
610
611 // warn user if # structured dependents != # structure alignments
612 // if (structureAlignments && nStructuredDependents !=
613 // structureAlignments->GetFeatures().front().GetObject().GetFeatures().size())
614 // ERRORMSG("Warning: Structure alignment list does not contain one alignment per "
615 // "structured sequence!\nYou should recompute structure alignments before saving "
616 // "in order to sync the lists.");
617 }
618
WriteDataToFile(const char * filename,bool isBinary,string * err,ncbi::EFixNonPrint fixNonPrint) const619 bool ASNDataManager::WriteDataToFile(const char *filename, bool isBinary,
620 string *err, ncbi::EFixNonPrint fixNonPrint) const
621 {
622 if (mimeData.NotEmpty())
623 return WriteASNToFile(filename, mimeData.GetObject(), isBinary, err, fixNonPrint);
624 else
625 return WriteASNToFile(filename, cddData.GetObject(), isBinary, err, fixNonPrint);
626 }
627
GetInternalCDDData(void)628 ncbi::objects::CCdd * ASNDataManager::GetInternalCDDData(void)
629 {
630 if (cddData.NotEmpty()) return cddData.GetPointer();
631 else if (mimeData.NotEmpty() && mimeData->IsGeneral() &&
632 mimeData->GetGeneral().GetSeq_align_data().IsCdd())
633 return &(mimeData->SetGeneral().SetSeq_align_data().SetCdd());
634 else
635 return NULL;
636 }
637
GetInternalCDDData(void) const638 const ncbi::objects::CCdd * ASNDataManager::GetInternalCDDData(void) const
639 {
640 if (cddData.NotEmpty()) return cddData.GetPointer();
641 else if (mimeData.NotEmpty() && mimeData->IsGeneral() &&
642 mimeData->GetGeneral().GetSeq_align_data().IsCdd())
643 return &(mimeData->GetGeneral().GetSeq_align_data().GetCdd());
644 else
645 return NULL;
646 }
647
IsCDD(void) const648 bool ASNDataManager::IsCDD(void) const
649 {
650 return (GetInternalCDDData() != NULL);
651 }
652
IsCDDInMime(void) const653 bool ASNDataManager::IsCDDInMime(void) const
654 {
655 return (GetInternalCDDData() != NULL && mimeData.NotEmpty());
656 }
657
GetCDDName(void) const658 const string& ASNDataManager::GetCDDName(void) const
659 {
660 static const string empty = "";
661 const CCdd *cdd = GetInternalCDDData();
662 if (cdd)
663 return cdd->GetName();
664 else
665 return empty;
666 }
667
SetCDDName(const string & name)668 bool ASNDataManager::SetCDDName(const string& name)
669 {
670 CCdd *cdd = GetInternalCDDData();
671 if (!cdd || name.size() == 0) return false;
672 cdd->SetName(name);
673 SetDataChanged(StructureSet::eCDDData);
674 return true;
675 }
676
GetCDDDescription(void) const677 const string& ASNDataManager::GetCDDDescription(void) const
678 {
679 static const string empty = "";
680 const CCdd *cdd = GetInternalCDDData();
681 if (!cdd) return empty;
682
683 // find first 'comment' in Cdd-descr-set, assume this is the "long description"
684 if (!cdd->IsSetDescription() || cdd->GetDescription().Get().size() == 0) return empty;
685 CCdd_descr_set::Tdata::const_iterator d, de = cdd->GetDescription().Get().end();
686 for (d=cdd->GetDescription().Get().begin(); d!=de; ++d)
687 if ((*d)->IsComment())
688 return (*d)->GetComment();
689
690 return empty;
691 }
692
SetCDDDescription(const string & descr)693 bool ASNDataManager::SetCDDDescription(const string& descr)
694 {
695 CCdd *cdd = GetInternalCDDData();
696 if (!cdd) return false;
697
698 if (cdd->IsSetDescription() && cdd->GetDescription().Get().size() > 0) {
699 // find first 'comment' in Cdd-descr-set, assume this is the "long description"
700 CCdd_descr_set::Tdata::iterator d, de = cdd->SetDescription().Set().end();
701 for (d=cdd->SetDescription().Set().begin(); d!=de; ++d) {
702 if ((*d)->IsComment()) {
703 if ((*d)->GetComment() != descr) {
704 (*d)->SetComment(descr);
705 SetDataChanged(StructureSet::eCDDData);
706 }
707 return true;
708 }
709 }
710 }
711
712 // add new comment if not yet present
713 CRef < CCdd_descr > comment(new CCdd_descr);
714 comment->SetComment(descr);
715 cdd->SetDescription().Set().push_front(comment);
716 SetDataChanged(StructureSet::eCDDData);
717 return true;
718 }
719
GetCDDNotes(TextLines * lines) const720 bool ASNDataManager::GetCDDNotes(TextLines *lines) const
721 {
722 const CCdd *cdd = GetInternalCDDData();
723 if (!lines || !cdd) return false;
724 lines->clear();
725
726 if (!cdd->IsSetDescription() || cdd->GetDescription().Get().size() == 0)
727 return true;
728
729 // find scrapbook item
730 CCdd_descr_set::Tdata::const_iterator d, de = cdd->GetDescription().Get().end();
731 for (d=cdd->GetDescription().Get().begin(); d!=de; ++d) {
732 if ((*d)->IsScrapbook()) {
733
734 // fill out lines from scrapbook string list
735 lines->resize((*d)->GetScrapbook().size());
736 CCdd_descr::TScrapbook::const_iterator l, le = (*d)->GetScrapbook().end();
737 int i = 0;
738 for (l=(*d)->GetScrapbook().begin(); l!=le; ++l)
739 (*lines)[i++] = *l;
740 return true;
741 }
742 }
743 return true;
744 }
745
SetCDDNotes(const TextLines & lines)746 bool ASNDataManager::SetCDDNotes(const TextLines& lines)
747 {
748 CCdd *cdd = GetInternalCDDData();
749 if (!cdd) return false;
750
751 CCdd_descr::TScrapbook *scrapbook = NULL;
752
753 // find an existing scrapbook item
754 if (cdd->IsSetDescription()) {
755 CCdd_descr_set::Tdata::iterator d, de = cdd->SetDescription().Set().end();
756 for (d=cdd->SetDescription().Set().begin(); d!=de; ++d) {
757 if ((*d)->IsScrapbook()) {
758 if (lines.size() == 0) {
759 cdd->SetDescription().Set().erase(d); // if empty, remove scrapbook item
760 SetDataChanged(StructureSet::eCDDData);
761 TRACEMSG("removed scrapbook");
762 } else
763 scrapbook = &((*d)->SetScrapbook());
764 break;
765 }
766 }
767 }
768 if (lines.size() == 0) return true;
769
770 // create a scrapbook item if doesn't exist already
771 if (!scrapbook) {
772 CRef < CCdd_descr > descr(new CCdd_descr());
773 scrapbook = &(descr->SetScrapbook());
774 cdd->SetDescription().Set().push_back(descr);
775 }
776
777 // fill out scrapbook lines
778 scrapbook->clear();
779 for (unsigned int i=0; i<lines.size(); ++i)
780 scrapbook->push_back(lines[i]);
781 SetDataChanged(StructureSet::eCDDData);
782
783 return true;
784 }
785
GetCDDDescrSet(void)786 ncbi::objects::CCdd_descr_set * ASNDataManager::GetCDDDescrSet(void)
787 {
788 CCdd *cdd = GetInternalCDDData();
789 if (cdd) {
790 // make a new descr set if not present
791 if (!cdd->IsSetDescription()) {
792 CRef < CCdd_descr_set > ref(new CCdd_descr_set());
793 cdd->SetDescription(*ref);
794 }
795 return &(cdd->SetDescription());
796 } else
797 return NULL;
798 }
799
GetCDDAnnotSet(void)800 ncbi::objects::CAlign_annot_set * ASNDataManager::GetCDDAnnotSet(void)
801 {
802 CCdd *cdd = GetInternalCDDData();
803 if (cdd) {
804 // make a new annot set if not present
805 if (!cdd->IsSetAlignannot()) {
806 CRef < CAlign_annot_set > ref(new CAlign_annot_set());
807 cdd->SetAlignannot(*ref);
808 }
809 return &(cdd->SetAlignannot());
810 } else
811 return NULL;
812 }
813
GetCDDMaster3d(void) const814 const ncbi::objects::CSeq_id * ASNDataManager::GetCDDMaster3d(void) const
815 {
816 const CCdd *cdd = GetInternalCDDData();
817 if (cdd && cdd->IsSetMaster3d() && cdd->GetMaster3d().size() > 0)
818 return cdd->GetMaster3d().front().GetPointer(); // just return the first one...
819 else
820 return NULL;
821 }
822
AddReject(ncbi::objects::CReject_id * reject)823 void ASNDataManager::AddReject(ncbi::objects::CReject_id *reject)
824 {
825 CCdd *cdd = GetInternalCDDData();
826 if (!cdd) return;
827
828 cdd->SetRejects().push_back(CRef < CReject_id > (reject));
829 dataChanged |= StructureSet::eCDDData;
830 }
831
GetRejects(void) const832 const StructureSet::RejectList * ASNDataManager::GetRejects(void) const
833 {
834 const CCdd *cdd = GetInternalCDDData();
835 if (!cdd || !cdd->IsSetRejects())
836 return NULL;
837 return &(cdd->GetRejects());
838 }
839
840 // the following three Check... functions are taken from CDTree2
841
CheckOneDenDiag(CRef<CDense_diag> & DenDiag,string & Str)842 bool CheckOneDenDiag(CRef<CDense_diag>& DenDiag, string& Str) {
843 //---------------------------------------------------------------------------
844 // check integrity of DenDiag.
845 //---------------------------------------------------------------------------
846 int Start1, Start2, Len, Dim;
847 char buf[1024];
848 bool RetVal = true;
849
850 // check that Dim of this dense-diag is exactly 2
851 Dim = DenDiag->GetDim();
852 if (Dim != 2) {
853 sprintf(buf, "Dense-diag Dim = %d. It should always be exactly 2.\n", Dim);
854 RetVal = false;
855 }
856
857 // check that Len of this dense-diag is at least 1
858 Len = DenDiag->GetLen();
859 if (Len < 0) {
860 sprintf(buf, "Dense-diag Len = %d. It should always be non-negative.\n", Len);
861 RetVal = false;
862 }
863
864 // check that Start of first row is sensible.
865 Start1 = DenDiag->GetStarts().front();
866 if (Start1 < 0) {
867 sprintf(buf, "Dense-diag has 1st row Start %d. It should always be non-negative.\n", Start1);
868 RetVal = false;
869 }
870
871 // check that Start of second row is sensible.
872 Start2 = DenDiag->GetStarts().back();
873 if (Start2 < 0) {
874 sprintf(buf, "Dense-diag has 2nd row start %d. It should always be non-negative.\n", Start2);
875 RetVal = false;
876 }
877
878 if (!RetVal) {
879 Str += buf;
880 }
881 return(RetVal);
882 }
883
CheckTwoDenDiags(CRef<CDense_diag> & DenDiag1,CRef<CDense_diag> & DenDiag2,string & Str)884 bool CheckTwoDenDiags(CRef<CDense_diag>& DenDiag1, CRef<CDense_diag>& DenDiag2, string& Str) {
885 //---------------------------------------------------------------------------
886 // check that DenDiag2 follows DenDiag1.
887 //---------------------------------------------------------------------------
888 int Start11, Start12, Start21, Start22, Len;
889 char buf[1024];
890 bool RetVal = true;
891
892 // get starts for first den-diag, and get its len
893 Start11 = DenDiag1->GetStarts().front();
894 Start12 = DenDiag1->GetStarts().back();
895 Len = DenDiag1->GetLen();
896
897 // get starts for second den-diag
898 Start21 = DenDiag2->GetStarts().front();
899 Start22 = DenDiag2->GetStarts().back();
900
901 // make sure starts for second den-diag follow starts for first
902 if (Start21 < (Start11 + Len)) {
903 sprintf(buf, "Dense-diag has 1st row Start %d, Len %d. Next Dense-diag has Start %d.\n", Start11, Len, Start21);
904 RetVal = false;
905 }
906
907 if (Start22 < (Start12 + Len)) {
908 sprintf(buf, "Dense-diag has 2nd row Start %d, Len %d. Next Dense-diag has Start %d.\n", Start12, Len, Start22);
909 RetVal = false;
910 }
911
912 if (!RetVal) {
913 Str += buf;
914 }
915 return(RetVal);
916 }
917
CheckOneAlignment(const CRef<CSeq_align> & SeqAlign,string & Str)918 bool CheckOneAlignment(const CRef<CSeq_align>& SeqAlign, string& Str) {
919 //---------------------------------------------------------------------------
920 // check integrity of one aligment
921 //---------------------------------------------------------------------------
922 list< CRef< CDense_diag > > DenDiags;
923 list< CRef< CDense_diag > >::iterator dd_iter;
924 CRef< CDense_diag > DenDiag1, DenDiag2;
925 bool RetVal = true;
926
927 // if alignment has no dense-diags go to next alignment
928 if (!SeqAlign->GetSegs().IsDendiag()) return(RetVal);
929
930 // get den-diags of alignment
931 DenDiags = SeqAlign->GetSegs().GetDendiag();
932
933 // get first den-diag
934 dd_iter = DenDiags.begin();
935 DenDiag1 = *dd_iter;
936
937 // check integrity of first den-diag
938 if (!CheckOneDenDiag(DenDiag1, Str)) RetVal = false;
939
940 // handle case when there's just one den-diag in the alignment
941 if (dd_iter == DenDiags.end()) return(RetVal);
942 dd_iter++;
943
944 // loop through the den-diags. make sure we're ascending.
945 for (; dd_iter != DenDiags.end(); dd_iter++) {
946 // get next den-diag
947 DenDiag2 = *dd_iter;
948 // check integrity of this den-diag
949 if (!CheckOneDenDiag(DenDiag2, Str)) RetVal = false;
950 // check that this den-diag is later in the sequence than preceeding den-diag
951 if (!CheckTwoDenDiags(DenDiag1, DenDiag2, Str)) RetVal = false;
952 DenDiag1 = DenDiag2;
953 }
954 return(RetVal);
955 }
956
MonitorAlignments(void) const957 bool ASNDataManager::MonitorAlignments(void) const
958 {
959 #ifndef _DEBUG
960 return true;
961
962 #else
963 // ... for development only...
964 bool okay = true;
965 string messages;
966 char buf[1024];
967
968 // check regular alignments
969 const SeqAnnotList *seqAnnots = GetSequenceAlignments();
970 if (seqAnnots) {
971 SeqAnnotList::const_iterator a, ae = seqAnnots->end();
972 for (a=seqAnnots->begin(); a!=ae; ++a) {
973 if ((*a)->GetData().IsAlign()) {
974 CSeq_annot::C_Data::TAlign::const_iterator s, se = (*a)->GetData().GetAlign().end();
975 int n = 1;
976 for (s=(*a)->GetData().GetAlign().begin(); s!=se; ++s, ++n) {
977 if (!CheckOneAlignment(*s, messages)) {
978 okay = false;
979 sprintf(buf, "Normal Alignment #%i\n\n", n);
980 messages += buf;
981 }
982 }
983 }
984 }
985 }
986
987 // check update alignments
988 const UpdateAlignList *updates = GetUpdates();
989 if (updates) {
990 UpdateAlignList::const_iterator u, ue = updates->end();
991 for (u=updates->begin(); u!=ue; ++u) {
992 if ((*u)->IsSetSeqannot() && (*u)->GetSeqannot().GetData().IsAlign()) {
993 CSeq_annot::C_Data::TAlign::const_iterator s, se = (*u)->GetSeqannot().GetData().GetAlign().end();
994 int n = 1;
995 for (s=(*u)->GetSeqannot().GetData().GetAlign().begin(); s!=se; ++s, ++n) {
996 if (!CheckOneAlignment(*s, messages)) {
997 okay = false;
998 sprintf(buf, "Pending Alignment #%i\n\n", n);
999 messages += buf;
1000 }
1001 }
1002 }
1003 }
1004 }
1005
1006 if (okay)
1007 TRACEMSG("MonitorAlignments() succeeded");
1008 else {
1009 ERRORMSG("MonitorAlignments() found errors, see log for details; please copy&paste and send a complete report to cdt-swg");
1010 WARNINGMSG("MonitorAlignments() found errors:\n\n" << messages);
1011 }
1012 return okay;
1013 #endif
1014 }
1015
CreateMimeFromBiostruc(const string & filename,EModel_type model)1016 CNcbi_mime_asn1 * CreateMimeFromBiostruc(const string& filename, EModel_type model)
1017 {
1018 // read Biostruc
1019 CRef < CBiostruc > biostruc(new CBiostruc());
1020 string err;
1021 SetDiagPostLevel(eDiag_Fatal); // ignore all but Fatal errors while reading data
1022 bool okay = (ReadASNFromFile(filename.c_str(), biostruc.GetPointer(), true, &err) ||
1023 ReadASNFromFile(filename.c_str(), biostruc.GetPointer(), false, &err));
1024 SetDiagPostLevel(eDiag_Info);
1025 if (!okay) {
1026 ERRORMSG("This file is not a valid Biostruc");
1027 TRACEMSG("err: " << err);
1028 return NULL;
1029 }
1030
1031 return CreateMimeFromBiostruc(biostruc, model);
1032 }
1033
CreateMimeFromBiostruc(CRef<CBiostruc> & biostruc,EModel_type model)1034 CNcbi_mime_asn1 * CreateMimeFromBiostruc(CRef < CBiostruc >& biostruc, EModel_type model)
1035 {
1036 // remove all but desired model coordinates
1037 list < CRef < CBiostruc_model > > desiredModels;
1038 CBiostruc::TModel::const_iterator m, me = biostruc->GetModel().end();
1039 for (m=biostruc->GetModel().begin(); m!=me; ++m) {
1040 if ((*m)->GetType() == model)
1041 desiredModels.push_back(*m);
1042 }
1043 if (desiredModels.size() == 0) {
1044 ERRORMSG("Ack! There's no appropriate model in this Biostruc");
1045 return NULL;
1046 }
1047 biostruc->ResetModel();
1048 biostruc->SetModel() = desiredModels;
1049
1050 // package Biostruc inside a mime object
1051 CRef < CNcbi_mime_asn1 > mime(new CNcbi_mime_asn1());
1052 CRef < CBiostruc_seq > strucseq(new CBiostruc_seq());
1053 mime->SetStrucseq(*strucseq);
1054 strucseq->SetStructure(*biostruc);
1055
1056 // get list of gi's to import
1057 vector < int > gis;
1058 CBiostruc_graph::TMolecule_graphs::const_iterator g,
1059 ge = biostruc->GetChemical_graph().GetMolecule_graphs().end();
1060 for (g=biostruc->GetChemical_graph().GetMolecule_graphs().begin(); g!=ge; ++g) {
1061 if ((*g)->IsSetSeq_id() && (*g)->GetSeq_id().IsGi())
1062 gis.push_back((*g)->GetSeq_id().GetGi());
1063 }
1064
1065 // fetch sequences and store in mime
1066 if (gis.size() > 0) {
1067 CRef < CSeq_entry > seqs(new CSeq_entry());
1068 strucseq->SetSequences().push_back(seqs);
1069 CRef < CBioseq_set > seqset(new CBioseq_set());
1070 seqs->SetSet(*seqset);
1071 for (unsigned int i=0; i<gis.size(); ++i) {
1072 CRef < CBioseq > bioseq = FetchSequenceViaHTTP(NStr::IntToString(gis[i]));
1073 if (bioseq.NotEmpty()) {
1074 CRef < CSeq_entry > seqentry(new CSeq_entry());
1075 seqentry->SetSeq(*bioseq);
1076 seqset->SetSeq_set().push_back(seqentry);
1077 } else {
1078 ERRORMSG("Failed to retrieve all Bioseqs");
1079 return NULL;
1080 }
1081 }
1082 } else
1083 WARNINGMSG("Can't find any sequence gi identifiers in this Biostruc");
1084
1085 return mime.Release();
1086 }
1087
1088 END_SCOPE(Cn3D)
1089