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 "SMatrix.h"
23
24 #include <U2Core/AppContext.h>
25 #include <U2Core/TextUtils.h>
26
27 namespace U2 {
28
29 #define DEFAULT_FILL_VALUE -1000000.0f
30
SMatrix(const QString & _name,const DNAAlphabet * _alphabet,const QList<SScore> & rawMatrix,const QString & _description)31 SMatrix::SMatrix(const QString &_name, const DNAAlphabet *_alphabet, const QList<SScore> &rawMatrix, const QString &_description)
32 : name(_name), description(_description), alphabet(_alphabet) {
33 validCharacters = alphabet->getAlphabetChars();
34 TextUtils::charBounds(validCharacters.constData(), validCharacters.size(), minChar, maxChar);
35 charsInRow = maxChar - minChar + 1;
36
37 scores.resize(charsInRow * charsInRow);
38 std::fill(scores.data(), scores.data() + scores.size(), -1000000);
39
40 minScore = 1000000;
41 maxScore = -1000000;
42 foreach (const SScore &s, rawMatrix) {
43 int idx = getScoreIdx(s.c1, s.c2);
44 scores[idx] = s.score;
45 minScore = qMin(minScore, s.score);
46 maxScore = qMax(maxScore, s.score);
47 }
48
49 // try to fix amino alphabet for extended symbols if needed: U(Selenocysteine) & O(Pyrrolysine)
50 if (alphabet->isAmino()) {
51 if (getScore('U', 'U') == DEFAULT_FILL_VALUE) { // no score for 'U' symbol, use score value for 'C' (Cysteine)
52 copyCharValues('C', 'U');
53 }
54 if (getScore('O', 'O') == DEFAULT_FILL_VALUE) { // no score for 'O' symbol, use score value for 'K' (Lysine)
55 copyCharValues('K', 'O');
56 }
57 }
58
59 // now for all symbols in alphabet without score set the minimal score
60 for (char c1: qAsConst(validCharacters)) {
61 for (char c2: qAsConst(validCharacters)) {
62 float score = getScore(c1, c2);
63 if (score == DEFAULT_FILL_VALUE) {
64 setScore(c1, c2, minScore);
65 }
66 }
67 }
68 }
69
copyCharValues(char srcChar,char dstChar)70 void SMatrix::copyCharValues(char srcChar, char dstChar) {
71 for (int i = 0; i < validCharacters.size(); i++) {
72 char c = validCharacters.at(i);
73 float scoreSrc1 = getScore(srcChar, c);
74 setScore(dstChar, c, scoreSrc1);
75 float scoreSrc2 = getScore(c, srcChar);
76 setScore(c, dstChar, scoreSrc2);
77 }
78 }
79
toQVariant() const80 QVariant SMatrix::toQVariant() const {
81 QList<QVariant> res;
82 res.append(name);
83 res.append(description);
84 res.append(alphabet->getId());
85 res.append(QChar(minChar));
86 res.append(QChar(maxChar));
87 res.append(charsInRow);
88 res.append(validCharacters);
89 res.append(double(minScore));
90 res.append(double(maxScore));
91
92 res.append(scores.size());
93 for (int i = 0; i < scores.size(); i++) {
94 res.append(double(scores[i]));
95 }
96
97 return res;
98 }
99
fromQVariant(const QVariant & v)100 SMatrix SMatrix::fromQVariant(const QVariant &v) {
101 QList<QVariant> list = v.toList();
102 SMatrix m;
103
104 int n = 0;
105 m.name = list.at(n++).toString();
106 m.description = list.at(n++).toString();
107 QString alphabetId = list.at(n++).toString();
108 m.alphabet = AppContext::getDNAAlphabetRegistry()->findById(alphabetId);
109 m.minChar = list.at(n++).toChar().toLatin1();
110 m.maxChar = list.at(n++).toChar().toLatin1();
111 m.charsInRow = list.at(n++).toInt();
112 m.validCharacters = list.at(n++).toByteArray();
113 m.minScore = (float)list.at(n++).toDouble();
114 m.maxScore = (float)list.at(n++).toDouble();
115
116 int nScores = list.at(n++).toInt();
117 m.scores.resize(nScores);
118 for (int i = 0; i < nScores; i++) {
119 m.scores[i] = float(list.at(n++).toDouble());
120 }
121
122 if (m.name.isEmpty() || m.alphabet == nullptr || m.validCharacters.isEmpty() || !m.validCharacters.contains(m.minChar) || !m.validCharacters.contains(m.maxChar) || m.maxChar - m.minChar + 1 != m.charsInRow) {
123 coreLog.error("Error during substitution matrix deserialization!");
124 return SMatrix();
125 }
126 return m;
127 }
128
129 } // namespace U2
130