1 
2 /*  $Id: psl_formatter.cpp 632624 2021-06-03 17:38:23Z ivanov $
3  * ===========================================================================
4  *
5  *                            PUBLIC DOMAIN NOTICE
6  *               National Center for Biotechnology Information
7  *
8  *  This software/database is a "United States Government Work" under the
9  *  terms of the United States Copyright Act.  It was written as part of
10  *  the author's official duties as a United States Government employee and
11  *  thus cannot be copyrighted.  This software/database is freely available
12  *  to the public for use. The National Library of Medicine and the U.S.
13  *  Government have not placed any restriction on its use or reproduction.
14  *
15  *  Although all reasonable efforts have been taken to ensure the accuracy
16  *  and reliability of the software and data, the NLM and the U.S.
17  *  Government do not and cannot warrant the performance or results that
18  *  may be obtained by using this software or data. The NLM and the U.S.
19  *  Government disclaim all warranties, express or implied, including
20  *  warranties of performance, merchantability or fitness for any particular
21  *  purpose.
22  *
23  *  Please cite the author in any work or product based on this material.
24  *
25  * ===========================================================================
26  *
27  * Authors:  Frank Ludwig
28  *
29  * File Description:  Write alignment
30  *
31  */
32 
33 #include <ncbi_pch.hpp>
34 
35 #include "psl_record.hpp"
36 #include "psl_formatter.hpp"
37 
38 BEGIN_NCBI_SCOPE
39 USING_SCOPE(objects);
40 
41 //  ----------------------------------------------------------------------------
42 static string
sDebugFormatValue(const string & label,const string & data)43 sDebugFormatValue(
44     const string& label,
45     const string& data)
46 //  ----------------------------------------------------------------------------
47 {
48     string formattedValue = (label + string(12, ' ')).substr(0, 12) + ": ";
49     formattedValue += data;
50     formattedValue += "\n";
51     return formattedValue;
52 }
53 
54 //  ----------------------------------------------------------------------------
55 static void
sDebugChunkArray(const vector<int> & origArray,int chunkSize,vector<vector<int>> & chunks)56 sDebugChunkArray(
57     const vector<int>& origArray,
58     int chunkSize,
59     vector<vector<int>>& chunks)
60 //  ----------------------------------------------------------------------------
61 {
62     if (origArray.empty()) {
63         return;
64     }
65     auto numElements = origArray.size();
66     for (auto index=0; index < numElements; ++index) {
67         if (0 == index % chunkSize) {
68             chunks.push_back(vector<int>());
69         }
70         chunks.back().push_back(origArray[index]);
71     }
72 }
73 
74 //  ----------------------------------------------------------------------------
75 static string
sFormatInt(int value,int dflt)76 sFormatInt(
77     int value,
78     int dflt)
79 //  ----------------------------------------------------------------------------
80 {
81     if (value == dflt) {
82         return ".";
83     }
84     return NStr::IntToString(value);
85 }
86 
87 //  ----------------------------------------------------------------------------
CPslFormatter(CNcbiOstream & ostr,bool debugMode)88 CPslFormatter::CPslFormatter(
89     CNcbiOstream& ostr,
90     bool debugMode):
91 //  ----------------------------------------------------------------------------
92     mOstr(ostr),
93     mDebugMode(debugMode)
94 {
95 }
96 
97 //  ----------------------------------------------------------------------------
98 string
xFieldMatches(const CPslRecord & record) const99 CPslFormatter::xFieldMatches(
100     const CPslRecord& record) const
101 //  ----------------------------------------------------------------------------
102 {
103     auto rawString = sFormatInt(record.GetMatches(), -1);
104     if (mDebugMode) {
105         return sDebugFormatValue("matches", rawString);
106     }
107     return rawString;
108 }
109 
110 //  ----------------------------------------------------------------------------
111 string
xFieldMisMatches(const CPslRecord & record) const112 CPslFormatter::xFieldMisMatches(
113     const CPslRecord& record) const
114 //  ----------------------------------------------------------------------------
115 {
116     auto rawString = sFormatInt(record.GetMisMatches(), -1);
117     if (mDebugMode) {
118         return sDebugFormatValue("misMatches", rawString);
119     }
120     return "\t" + rawString;
121 }
122 
123 //  ----------------------------------------------------------------------------
124 string
xFieldRepMatches(const CPslRecord & record) const125 CPslFormatter::xFieldRepMatches(
126     const CPslRecord& record) const
127 //  ----------------------------------------------------------------------------
128 {
129     auto rawString = sFormatInt(record.GetRepMatches(), -1);
130     if (mDebugMode) {
131         return sDebugFormatValue("repMatches", rawString);
132     }
133     return "\t" + rawString;
134 }
135 
136 //  ----------------------------------------------------------------------------
137 string
xFieldCountN(const CPslRecord & record) const138 CPslFormatter::xFieldCountN(
139     const CPslRecord& record) const
140 //  ----------------------------------------------------------------------------
141 {
142     auto rawString = sFormatInt(record.GetCountN(), -1);
143     if (mDebugMode) {
144         return sDebugFormatValue("nCount", rawString);
145     }
146     return "\t" + rawString;
147 }
148 
149 //  ----------------------------------------------------------------------------
150 string
xFieldNumInsertQ(const CPslRecord & record) const151 CPslFormatter::xFieldNumInsertQ(
152     const CPslRecord& record) const
153 //  ----------------------------------------------------------------------------
154 {
155     auto rawString = sFormatInt(record.GetNumInsertQ(), -1);
156     if (mDebugMode) {
157         return sDebugFormatValue("qNumInsert", rawString);
158     }
159     return "\t" + rawString;
160 }
161 
162 //  ----------------------------------------------------------------------------
163 string
xFieldBaseInsertQ(const CPslRecord & record) const164 CPslFormatter::xFieldBaseInsertQ(
165     const CPslRecord& record) const
166 //  ----------------------------------------------------------------------------
167 {
168     auto rawString = sFormatInt(record.GetBaseInsertQ(), -1);
169     if (mDebugMode) {
170         return sDebugFormatValue("qBaseInsert", rawString);
171     }
172     return "\t" + rawString;
173 }
174 
175 //  ----------------------------------------------------------------------------
176 string
xFieldNumInsertT(const CPslRecord & record) const177 CPslFormatter::xFieldNumInsertT(
178     const CPslRecord& record) const
179 //  ----------------------------------------------------------------------------
180 {
181     auto rawString = sFormatInt(record.GetNumInsertT(), -1);
182     if (mDebugMode) {
183         return sDebugFormatValue("tNumInsert", rawString);
184     }
185     return "\t" + rawString;
186 }
187 
188 //  ----------------------------------------------------------------------------
189 string
xFieldBaseInsertT(const CPslRecord & record) const190 CPslFormatter::xFieldBaseInsertT(
191     const CPslRecord& record) const
192 //  ----------------------------------------------------------------------------
193 {
194     auto rawString = sFormatInt(record.GetBaseInsertT(), -1);
195     if (mDebugMode) {
196         return sDebugFormatValue("tBaseInsert", rawString);
197     }
198     return "\t" + rawString;
199 }
200 
201 //  ----------------------------------------------------------------------------
202 string
xFieldStrand(const CPslRecord & record) const203 CPslFormatter::xFieldStrand(
204     const CPslRecord& record) const
205 //  ----------------------------------------------------------------------------
206 {
207     string rawString = ".";
208     if (record.GetStrandT() != eNa_strand_unknown) {
209         rawString = (record.GetStrandT() == eNa_strand_minus ? "-" : "+");
210     }
211     if (mDebugMode) {
212         return sDebugFormatValue("strand", rawString);
213     }
214     return "\t" + rawString;
215 }
216 
217 //  ----------------------------------------------------------------------------
218 string
xFieldNameQ(const CPslRecord & record) const219 CPslFormatter::xFieldNameQ(
220     const CPslRecord& record) const
221 //  ----------------------------------------------------------------------------
222 {
223     auto rawString = record.GetNameQ();
224     if (rawString.empty()) {
225         rawString = ".";
226     }
227     if (mDebugMode) {
228         return sDebugFormatValue("qName", rawString);
229     }
230     return "\t" + rawString;
231 }
232 
233 //  ----------------------------------------------------------------------------
234 string
xFieldSizeQ(const CPslRecord & record) const235 CPslFormatter::xFieldSizeQ(
236     const CPslRecord& record) const
237 //  ----------------------------------------------------------------------------
238 {
239     auto rawString = sFormatInt(record.GetSizeQ(), -1);
240      if (mDebugMode) {
241         return sDebugFormatValue("qSize", rawString);
242     }
243     return "\t" + rawString;
244 }
245 
246 //  ----------------------------------------------------------------------------
247 string
xFieldStartQ(const CPslRecord & record) const248 CPslFormatter::xFieldStartQ(
249     const CPslRecord& record) const
250 //  ----------------------------------------------------------------------------
251 {
252     auto rawString = sFormatInt(record.GetStartQ(), -1);
253     if (mDebugMode) {
254         return sDebugFormatValue("qStart", rawString);
255     }
256     return "\t" + rawString;
257 }
258 
259 //  ----------------------------------------------------------------------------
260 string
xFieldEndQ(const CPslRecord & record) const261 CPslFormatter::xFieldEndQ(
262     const CPslRecord& record) const
263 //  ----------------------------------------------------------------------------
264 {
265     auto rawString = sFormatInt(record.GetEndQ(), -1);
266     if (mDebugMode) {
267         return sDebugFormatValue("qEnd", rawString);
268     }
269     return "\t" + rawString;
270 }
271 
272 //  ----------------------------------------------------------------------------
273 string
xFieldNameT(const CPslRecord & record) const274 CPslFormatter::xFieldNameT(
275     const CPslRecord& record) const
276 //  ----------------------------------------------------------------------------
277 {
278     auto rawString = record.GetNameT();
279     if (rawString.empty()) {
280         rawString = ".";
281     }
282     if (mDebugMode) {
283         return sDebugFormatValue("tName", rawString);
284     }
285     return "\t" + rawString;
286 }
287 
288 //  ----------------------------------------------------------------------------
289 string
xFieldSizeT(const CPslRecord & record) const290 CPslFormatter::xFieldSizeT(
291     const CPslRecord& record) const
292 //  ----------------------------------------------------------------------------
293 {
294     auto rawString = sFormatInt(record.GetSizeT(), -1);
295     if (mDebugMode) {
296         return sDebugFormatValue("tSize", rawString);
297     }
298     return "\t" + rawString;
299 }
300 
301 //  ----------------------------------------------------------------------------
302 string
xFieldStartT(const CPslRecord & record) const303 CPslFormatter::xFieldStartT(
304     const CPslRecord& record) const
305 //  ----------------------------------------------------------------------------
306 {
307     auto rawString = sFormatInt(record.GetStartT(), -1);
308     if (mDebugMode) {
309        return sDebugFormatValue("tStart", rawString);
310     }
311     return "\t" + rawString;
312 }
313 
314 //  ----------------------------------------------------------------------------
315 string
xFieldEndT(const CPslRecord & record) const316 CPslFormatter::xFieldEndT(
317     const CPslRecord& record) const
318 //  ----------------------------------------------------------------------------
319 {
320     auto rawString = sFormatInt(record.GetEndT(), -1);
321     if (mDebugMode) {
322         return sDebugFormatValue("tEnd", rawString);
323     }
324     return "\t" + rawString;
325 }
326 
327 //  ----------------------------------------------------------------------------
328 string
xFieldBlockCount(const CPslRecord & record) const329 CPslFormatter::xFieldBlockCount(
330     const CPslRecord& record) const
331 //  ----------------------------------------------------------------------------
332 {
333     auto rawString = sFormatInt(record.GetBlockCount(), -1);
334     if (mDebugMode) {
335         return sDebugFormatValue("blockCount", rawString);
336     }
337     return "\t" + rawString;
338 }
339 
340 //  ----------------------------------------------------------------------------
341 string
xFieldBlockSizes(const CPslRecord & record) const342 CPslFormatter::xFieldBlockSizes(
343     const CPslRecord& record) const
344 //  ----------------------------------------------------------------------------
345 {
346     auto blockSizes = record.GetBlockSizes();
347     if (mDebugMode) {
348         if (blockSizes.empty()) {
349             return sDebugFormatValue("blockSizes", ".");
350         }
351         vector<vector<int>> chunks;
352         sDebugChunkArray(blockSizes, 5, chunks);
353         bool labelWritten = false;
354         string field;
355         for (auto& chunk: chunks) {
356             auto value = NStr::JoinNumeric(chunk.begin(), chunk.end(), ", ");
357             if (!labelWritten) {
358                 field += sDebugFormatValue("blockSizes", value);
359                 labelWritten = true;
360             }
361             else {
362                 field += "              ";
363                 field += value;
364                 field += "\n";
365             }
366         }
367         return field;
368     }
369     return "\t" + NStr::JoinNumeric(blockSizes.begin(), blockSizes.end(), ",");
370 }
371 
372 //  ----------------------------------------------------------------------------
373 string
xFieldStartsQ(const CPslRecord & record) const374 CPslFormatter::xFieldStartsQ(
375     const CPslRecord& record) const
376 //  ----------------------------------------------------------------------------
377 {
378     auto blockStartsQ = record.GetBlockStartsQ();
379     if (mDebugMode) {
380         if (blockStartsQ.empty()) {
381             return sDebugFormatValue("qStarts", ".");
382         }
383         vector<vector<int>> chunks;
384         sDebugChunkArray(blockStartsQ, 5, chunks);
385         bool labelWritten = false;
386         string field;
387         for (auto& chunk: chunks) {
388             auto value = NStr::JoinNumeric(chunk.begin(), chunk.end(), ", ");
389             if (!labelWritten) {
390                 field += sDebugFormatValue("qStarts", value);
391                 labelWritten = true;
392             }
393             else {
394                 field += "              ";
395                 field += value;
396                 field += "\n";
397             }
398         }
399         return field;
400     }
401     return "\t" + NStr::JoinNumeric(blockStartsQ.begin(), blockStartsQ.end(), ",");
402 }
403 
404 //  ----------------------------------------------------------------------------
405 string
xFieldStartsT(const CPslRecord & record) const406 CPslFormatter::xFieldStartsT(
407     const CPslRecord& record) const
408 //  ----------------------------------------------------------------------------
409 {
410     auto blockStartsT = record.GetBlockStartsT();
411     if (mDebugMode) {
412         if (blockStartsT.empty()) {
413             return sDebugFormatValue("tStarts", ".");
414         }
415         vector<vector<int>> chunks;
416         sDebugChunkArray(blockStartsT, 5, chunks);
417         bool labelWritten = false;
418         string field;
419         for (auto& chunk: chunks) {
420             auto value = NStr::JoinNumeric(chunk.begin(), chunk.end(), ", ");
421             if (!labelWritten) {
422                 field += sDebugFormatValue("tStarts", value);
423                 labelWritten = true;
424             }
425             else {
426                 field += "              ";
427                 field += value;
428                 field += "\n";
429             }
430         }
431         return field;
432     }
433     return "\t" + NStr::JoinNumeric(blockStartsT.begin(), blockStartsT.end(), ",");
434 }
435 
436 //  ----------------------------------------------------------------------------
437 void
Format(const CPslRecord & record)438 CPslFormatter::Format(
439     const CPslRecord& record)
440 //  ----------------------------------------------------------------------------
441 {
442     mOstr << xFieldMatches(record)
443          << xFieldMisMatches(record)
444          << xFieldRepMatches(record)
445          << xFieldCountN(record)
446          << xFieldNumInsertQ(record)
447          << xFieldBaseInsertQ(record)
448          << xFieldNumInsertT(record)
449          << xFieldBaseInsertT(record)
450          << xFieldStrand(record)
451          << xFieldNameQ(record)
452          << xFieldSizeQ(record)
453          << xFieldStartQ(record)
454          << xFieldEndQ(record)
455          << xFieldNameT(record)
456          << xFieldSizeT(record)
457          << xFieldStartT(record)
458          << xFieldEndT(record)
459          << xFieldBlockCount(record)
460          << xFieldBlockSizes(record)
461          << xFieldStartsQ(record)
462          << xFieldStartsT(record)
463          << endl;
464 }
465 
466 END_NCBI_SCOPE
467 
468