| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* BEGIN software license | ||
| 2 | * | ||
| 3 | * MsXpertSuite - mass spectrometry software suite | ||
| 4 | * ----------------------------------------------- | ||
| 5 | * Copyright(C) 2009,...,2018 Filippo Rusconi | ||
| 6 | * | ||
| 7 | * http://www.msxpertsuite.org | ||
| 8 | * | ||
| 9 | * This file is part of the MsXpertSuite project. | ||
| 10 | * | ||
| 11 | * The MsXpertSuite project is the successor of the massXpert project. This | ||
| 12 | * project now includes various independent modules: | ||
| 13 | * | ||
| 14 | * - massXpert, model polymer chemistries and simulate mass spectrometric data; | ||
| 15 | * - mineXpert, a powerful TIC chromatogram/mass spectrum viewer/miner; | ||
| 16 | * | ||
| 17 | * This program is free software: you can redistribute it and/or modify | ||
| 18 | * it under the terms of the GNU General Public License as published by | ||
| 19 | * the Free Software Foundation, either version 3 of the License, or | ||
| 20 | * (at your option) any later version. | ||
| 21 | * | ||
| 22 | * This program is distributed in the hope that it will be useful, | ||
| 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 25 | * GNU General Public License for more details. | ||
| 26 | * | ||
| 27 | * You should have received a copy of the GNU General Public License | ||
| 28 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 29 | * | ||
| 30 | * END software license | ||
| 31 | */ | ||
| 32 | |||
| 33 | |||
| 34 | /////////////////////// Qt includes | ||
| 35 | #include <QFile> | ||
| 36 | #include <QDebug> | ||
| 37 | #include <QRegularExpression> | ||
| 38 | #include <QRegularExpressionMatch> | ||
| 39 | |||
| 40 | |||
| 41 | /////////////////////// Local includes | ||
| 42 | #include "ModifSpec.hpp" | ||
| 43 | |||
| 44 | |||
| 45 | namespace MsXpS | ||
| 46 | { | ||
| 47 | |||
| 48 | namespace libXpertMass | ||
| 49 | { | ||
| 50 | |||
| 51 | |||
| 52 | /*! | ||
| 53 | \class MsXpS::libXpertMass::ModifSpec | ||
| 54 | \inmodule libXpertMass | ||
| 55 | \ingroup PolChemDefBuildingdBlocks | ||
| 56 | \inheaderfile ModifSpec.hpp | ||
| 57 | |||
| 58 | \brief The ModifSpec class provides the specification about how \l Modif | ||
| 59 | objects are represented. | ||
| 60 | |||
| 61 | The ModifSpec class specifies how a \l Modif object is represented | ||
| 62 | graphically, mainly by connecting its modif name to a graphics SVG file that | ||
| 63 | is located in the Polymer chemistry definition directory. That connection is | ||
| 64 | performed in the "modification_dictionary" dictionary file itself also located | ||
| 65 | in the polymer chemistry definition directory. Its contents look like this: | ||
| 66 | |||
| 67 | \code | ||
| 68 | Phosphorylation%T%phospho.svg | ||
| 69 | Sulphation%T%sulpho.svg | ||
| 70 | AmidationAsp%O%asparagine.svg | ||
| 71 | Acetylation%T%acetyl.svg | ||
| 72 | AmidationGlu%O%glutamine.svg | ||
| 73 | Oxidation%T%oxidation.svg | ||
| 74 | SulfideBond%T%sulfbond.svg | ||
| 75 | ProtonLoss%T%protonloss.svg | ||
| 76 | \endcode | ||
| 77 | |||
| 78 | The \c{Phosphorylation%T%phospho.svg} line indicates that, when a Monomer object | ||
| 79 | modified by a Modif object by name "Phosphorylation" is | ||
| 80 | to be rendered graphically, the corresponding vignette to be used is in the | ||
| 81 | file named "phospho.svg" in the polymer chemistry definition directory. The 'T' | ||
| 82 | and 'O' special directives, indicate the way the modification is to be | ||
| 83 | represented graphically in the sequence editor. When a monomer is modified, the | ||
| 84 | modification event can be shown by overlaying onto the monomer's vignette | ||
| 85 | a transparent vignette or by replacing it totally with a new one. | ||
| 86 | These two behaviours are documented above with the letters 'T' (transparent | ||
| 87 | overlay) or 'O' (opaque overwrite). | ||
| 88 | */ | ||
| 89 | |||
| 90 | /*! | ||
| 91 | \variable int MsXpS::libXpertMass::ModifSpec::m_name | ||
| 92 | |||
| 93 | \brief The name of the modification. | ||
| 94 | */ | ||
| 95 | |||
| 96 | /*! | ||
| 97 | \variable int MsXpS::libXpertMass::ModifSpec::m_action | ||
| 98 | |||
| 99 | \brief The graphics action (Opaque, that is, overwrite ; Transparent, that is, | ||
| 100 | overlay) of the modification. | ||
| 101 | */ | ||
| 102 | |||
| 103 | /*! | ||
| 104 | \variable int MsXpS::libXpertMass::ModifSpec::m_raster | ||
| 105 | |||
| 106 | \brief The file name of the raster representation of the modification. | ||
| 107 | */ | ||
| 108 | |||
| 109 | /*! | ||
| 110 | \variable int MsXpS::libXpertMass::ModifSpec::m_vector | ||
| 111 | |||
| 112 | \brief The filename of the vector representation of the modification. | ||
| 113 | */ | ||
| 114 | |||
| 115 | /*! | ||
| 116 | \variable int MsXpS::libXpertMass::ModifSpec::m_sound | ||
| 117 | |||
| 118 | \brief The file name of the sound for the name of the modification. | ||
| 119 | */ | ||
| 120 | |||
| 121 | |||
| 122 | /*! | ||
| 123 | \brief Constructs a ModifSpec instance. | ||
| 124 | */ | ||
| 125 | ✗ | ModifSpec::ModifSpec() | |
| 126 | { | ||
| 127 | ✗ | m_action = 0; | |
| 128 | ✗ | } | |
| 129 | |||
| 130 | /*! | ||
| 131 | \brief Destructs this ModifSpec instance. | ||
| 132 | */ | ||
| 133 | ✗ | ModifSpec::~ModifSpec() | |
| 134 | { | ||
| 135 | ✗ | } | |
| 136 | |||
| 137 | /*! | ||
| 138 | \brief Sets the monomer \a name. | ||
| 139 | */ | ||
| 140 | void | ||
| 141 | ✗ | ModifSpec::setName(const QString &name) | |
| 142 | { | ||
| 143 | ✗ | m_name = name; | |
| 144 | ✗ | } | |
| 145 | |||
| 146 | /*! | ||
| 147 | \brief Returns the monomer name. | ||
| 148 | */ | ||
| 149 | const QString & | ||
| 150 | ✗ | ModifSpec::name() | |
| 151 | { | ||
| 152 | ✗ | return m_name; | |
| 153 | } | ||
| 154 | |||
| 155 | |||
| 156 | /*! | ||
| 157 | \brief Sets the \a action. | ||
| 158 | |||
| 159 | The action is the way the Modif's vignette applies itself on top of the | ||
| 160 | \l{Monomer}'s vignette: either in an Opaque manner, thus overwriting the | ||
| 161 | initial vignette, or in a Transparent manner, thus only partially overlaying | ||
| 162 | the initial vignette. | ||
| 163 | */ | ||
| 164 | void | ||
| 165 | ✗ | ModifSpec::setAction(int action) | |
| 166 | { | ||
| 167 | ✗ | m_action = action; | |
| 168 | ✗ | } | |
| 169 | |||
| 170 | /*! | ||
| 171 | \brief Returns the action. | ||
| 172 | |||
| 173 | \sa setAction() | ||
| 174 | */ | ||
| 175 | int | ||
| 176 | ✗ | ModifSpec::action() | |
| 177 | { | ||
| 178 | ✗ | return m_action; | |
| 179 | } | ||
| 180 | |||
| 181 | |||
| 182 | /*! | ||
| 183 | \brief Sets the raster image file name to \a raster. | ||
| 184 | */ | ||
| 185 | void | ||
| 186 | ✗ | ModifSpec::setRaster(const QString &raster) | |
| 187 | { | ||
| 188 | ✗ | m_raster = raster; | |
| 189 | ✗ | } | |
| 190 | |||
| 191 | |||
| 192 | /*! | ||
| 193 | \brief Returns the raster image file name. | ||
| 194 | */ | ||
| 195 | const QString & | ||
| 196 | ✗ | ModifSpec::raster() | |
| 197 | { | ||
| 198 | ✗ | return m_raster; | |
| 199 | } | ||
| 200 | |||
| 201 | /*! | ||
| 202 | \brief Sets the vector image file name to \a vector. | ||
| 203 | */ | ||
| 204 | void | ||
| 205 | ✗ | ModifSpec::setVector(const QString &vector) | |
| 206 | { | ||
| 207 | ✗ | m_vector = vector; | |
| 208 | ✗ | } | |
| 209 | |||
| 210 | /*! | ||
| 211 | \brief Returns the vector image file name. | ||
| 212 | */ | ||
| 213 | const QString & | ||
| 214 | ✗ | ModifSpec::vector() | |
| 215 | { | ||
| 216 | ✗ | return m_vector; | |
| 217 | } | ||
| 218 | |||
| 219 | |||
| 220 | /*! | ||
| 221 | \brief Sets the file name of the Modif's \a sound file. | ||
| 222 | */ | ||
| 223 | void | ||
| 224 | ✗ | ModifSpec::setSound(const QString &sound) | |
| 225 | { | ||
| 226 | ✗ | m_sound = sound; | |
| 227 | ✗ | } | |
| 228 | |||
| 229 | |||
| 230 | /*! | ||
| 231 | \brief Returns the file name of the Modif's sound file. | ||
| 232 | */ | ||
| 233 | const QString & | ||
| 234 | ✗ | ModifSpec::sound() | |
| 235 | { | ||
| 236 | ✗ | return m_sound; | |
| 237 | } | ||
| 238 | |||
| 239 | |||
| 240 | /*! | ||
| 241 | \brief Parses the \a file_path dictionary containing the Modif | ||
| 242 | specifications. | ||
| 243 | |||
| 244 | At the moment the file has this format: | ||
| 245 | |||
| 246 | \code | ||
| 247 | Phosphorylation%T%phospho.svg | ||
| 248 | Sulphation%T%sulpho.svg | ||
| 249 | AmidationAsp%O%asparagine.svg | ||
| 250 | Acetylation%T%acetyl.svg | ||
| 251 | AmidationGlu%O%glutamine.svg | ||
| 252 | Oxidation%T%oxidation.svg | ||
| 253 | \endcode | ||
| 254 | |||
| 255 | Upon parsing, the \a modif_spec_list of ModifSpec instances will be filled with | ||
| 256 | instances created on the basis of each parsed line in the file. | ||
| 257 | |||
| 258 | Returns true if the parsing was successful, false otherwise. | ||
| 259 | */ | ||
| 260 | bool | ||
| 261 | ✗ | ModifSpec::parseFile(QString &file_path, QList<ModifSpec *> *modif_spec_list) | |
| 262 | { | ||
| 263 | ✗ | ModifSpec *modifSpec = 0; | |
| 264 | |||
| 265 | qint64 lineLength; | ||
| 266 | |||
| 267 | ✗ | QString line; | |
| 268 | ✗ | QString temp; | |
| 269 | |||
| 270 | char buffer[1024]; | ||
| 271 | |||
| 272 | ✗ | Q_ASSERT(modif_spec_list != 0); | |
| 273 | |||
| 274 | ✗ | if(file_path.isEmpty()) | |
| 275 | ✗ | return false; | |
| 276 | |||
| 277 | ✗ | QFile file(file_path); | |
| 278 | |||
| 279 | ✗ | if(!file.open(QFile::ReadOnly)) | |
| 280 | ✗ | return false; | |
| 281 | |||
| 282 | // The lines we have to parse are of the following type: | ||
| 283 | // Phosphorylation%T%phospho.svg | ||
| 284 | // Any line starting with '#' are not parsed. | ||
| 285 | |||
| 286 | // Get the first line of the file. Next we enter in to a | ||
| 287 | // while loop. | ||
| 288 | |||
| 289 | ✗ | lineLength = file.readLine(buffer, sizeof(buffer)); | |
| 290 | |||
| 291 | ✗ | while(lineLength != -1) | |
| 292 | { | ||
| 293 | // The line is now in buffer, and we want to convert | ||
| 294 | // it to Unicode by setting it in a QString. | ||
| 295 | ✗ | line = buffer; | |
| 296 | |||
| 297 | // The line that is in line should contain something like: | ||
| 298 | // Phosphorylation%T%phospho.svg | ||
| 299 | |||
| 300 | // Remove all the spaces from the borders: Whitespace means any | ||
| 301 | // character for which QChar::isSpace() returns true. This | ||
| 302 | // includes the ASCII characters '\t', '\n', '\v', '\f', '\r', | ||
| 303 | // and ' '. | ||
| 304 | |||
| 305 | ✗ | line = line.trimmed(); | |
| 306 | |||
| 307 | ✗ | if(line.isEmpty() || line.startsWith('#', Qt::CaseInsensitive)) | |
| 308 | { | ||
| 309 | ✗ | lineLength = file.readLine(buffer, sizeof(buffer)); | |
| 310 | ✗ | continue; | |
| 311 | } | ||
| 312 | |||
| 313 | ✗ | qDebug() << "Reading line:" << line; | |
| 314 | |||
| 315 | // Now some other checks. Remember the format of the line: | ||
| 316 | // Phosphorylation%T%phospho.svg | ||
| 317 | ✗ | QString modif_name; | |
| 318 | ✗ | QString file_name; | |
| 319 | ✗ | QString opacity; | |
| 320 | |||
| 321 | ✗ | QRegularExpression reg_exp(QString("^(.*)%([TO])%(.*)$")); | |
| 322 | |||
| 323 | ✗ | QRegularExpressionMatch match = reg_exp.match(line); | |
| 324 | |||
| 325 | ✗ | if(match.hasMatch()) | |
| 326 | { | ||
| 327 | ✗ | modif_name = match.captured(1); | |
| 328 | ✗ | opacity = match.captured(2); | |
| 329 | ✗ | file_name = match.captured(3); | |
| 330 | } | ||
| 331 | else | ||
| 332 | ✗ | return false; | |
| 333 | |||
| 334 | // qDebug() << "modif_name:" << modif_name << "opacity:" << opacity | ||
| 335 | // << "file_name:" << file_name; | ||
| 336 | |||
| 337 | // OK, we finally can allocate a new ModifSpec *. | ||
| 338 | ✗ | modifSpec = new ModifSpec(); | |
| 339 | |||
| 340 | ✗ | modifSpec->m_name = modif_name; | |
| 341 | ✗ | modifSpec->m_vector = file_name; | |
| 342 | |||
| 343 | ✗ | if(opacity == "O") | |
| 344 | ✗ | modifSpec->m_action = CompositingType::OPAQUE; | |
| 345 | ✗ | else if(opacity == "T") | |
| 346 | ✗ | modifSpec->m_action = CompositingType::TRANSPARENT; | |
| 347 | else | ||
| 348 | ✗ | qFatal("Programming error."); | |
| 349 | |||
| 350 | ✗ | modif_spec_list->append(modifSpec); | |
| 351 | ✗ | lineLength = file.readLine(buffer, sizeof(buffer)); | |
| 352 | ✗ | } | |
| 353 | |||
| 354 | ✗ | return true; | |
| 355 | ✗ | } | |
| 356 | |||
| 357 | } // namespace libXpertMass | ||
| 358 | |||
| 359 | } // namespace MsXpS | ||
| 360 |