File indexing completed on 2022-11-22 17:50:14

0001 /*
0002     SPDX-FileCopyrightText: 2005, 2006 Pino Toscano <toscano.pino@tiscali.it>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "kalziumgradienttype.h"
0008 
0009 #include "element.h"
0010 #include "kalziumdataobject.h"
0011 #include "prefs.h"
0012 
0013 #include "kalzium_debug.h"
0014 #include <QVariant>
0015 
0016 #include <KLocalizedString>
0017 #include <KUnitConversion/Converter>
0018 
0019 #include <cmath>
0020 
0021 KalziumGradientTypeFactory::KalziumGradientTypeFactory()
0022 {
0023     m_gradients << KalziumSOMGradientType::instance();
0024     m_gradients << KalziumCovalentRadiusGradientType::instance();
0025     m_gradients << KalziumVanDerWaalsRadiusGradientType::instance();
0026     m_gradients << KalziumMassGradientType::instance();
0027     m_gradients << KalziumBoilingPointGradientType::instance();
0028     m_gradients << KalziumMeltingPointGradientType::instance();
0029     m_gradients << KalziumElectronegativityGradientType::instance();
0030     m_gradients << KalziumElectronaffinityGradientType::instance();
0031     m_gradients << KalziumDiscoverydateGradientType::instance();
0032     m_gradients << KalziumIonizationGradientType::instance();
0033 }
0034 
0035 KalziumGradientTypeFactory *KalziumGradientTypeFactory::instance()
0036 {
0037     static KalziumGradientTypeFactory kttf;
0038     return &kttf;
0039 }
0040 
0041 KalziumGradientType *KalziumGradientTypeFactory::build(int id) const
0042 {
0043     if ((id < 0) || (id >= m_gradients.count()))
0044         return nullptr;
0045 
0046     return m_gradients.at(id);
0047 }
0048 
0049 KalziumGradientType *KalziumGradientTypeFactory::build(const QByteArray &id) const
0050 {
0051     for (int i = 0; i < m_gradients.count(); ++i) {
0052         if (m_gradients.at(i)->name() == id) {
0053             return m_gradients.at(i);
0054         }
0055     }
0056 
0057     return nullptr;
0058 }
0059 
0060 QStringList KalziumGradientTypeFactory::gradients() const
0061 {
0062     QStringList l;
0063     for (int i = 0; i < m_gradients.count(); ++i) {
0064         l << m_gradients.at(i)->description();
0065     }
0066     return l;
0067 }
0068 
0069 KalziumGradientType::KalziumGradientType() = default;
0070 
0071 KalziumGradientType::~KalziumGradientType() = default;
0072 
0073 KalziumGradientType *KalziumGradientType::instance()
0074 {
0075     return nullptr;
0076 }
0077 
0078 double KalziumGradientType::elementCoeff(int el) const
0079 {
0080     double val = value(el);
0081     if (val == -1) {
0082         return val;
0083     }
0084 
0085     if (logarithmicGradient()) {
0086         double minVal = minValue();
0087         double maxVal = maxValue();
0088 
0089         // Fixing negative values for log calculation (no negative values allowed -> NaN)
0090         if (minVal < 0) {
0091             minVal = abs(minVal) + 1; // make sure it's bigger than 0
0092             maxVal += minVal;
0093             val += minVal;
0094             minVal = 0.01;
0095         }
0096 
0097         double result = (log(val) - log(minVal)) / (log(maxVal) - log(minVal));
0098 
0099         // now we perform a "gamma-correction" on the result. Indeed, logarithmic gradients
0100         // often have the problem that all high values have roughly the same color. Note that
0101         // as firstColor() is not necessarily black and secondColor() is not necessarily white,
0102         // this is not exactly a "gamma-correction" in the usual sense.
0103         const double gamma = 1.4;
0104         result = exp(gamma * log(result));
0105         return result;
0106     } else {
0107         return (val - minValue()) / (maxValue() - minValue());
0108     }
0109 }
0110 
0111 QColor KalziumGradientType::firstColor() const
0112 {
0113     return Prefs::minColor();
0114 }
0115 
0116 QColor KalziumGradientType::secondColor() const
0117 {
0118     return Prefs::maxColor();
0119 }
0120 
0121 QColor KalziumGradientType::notAvailableColor() const
0122 {
0123     return Qt::lightGray;
0124 }
0125 
0126 QColor KalziumGradientType::calculateColor(const double coeff) const
0127 {
0128     if ((coeff < 0.0) || (coeff > 1.0))
0129         return notAvailableColor();
0130 
0131     QColor color2 = secondColor();
0132     QColor color1 = firstColor();
0133 
0134     int red = static_cast<int>((color2.red() - color1.red()) * coeff + color1.red());
0135     int green = static_cast<int>((color2.green() - color1.green()) * coeff + color1.green());
0136     int blue = static_cast<int>((color2.blue() - color1.blue()) * coeff + color1.blue());
0137 
0138     return {red, green, blue};
0139 }
0140 
0141 KalziumCovalentRadiusGradientType *KalziumCovalentRadiusGradientType::instance()
0142 {
0143     static KalziumCovalentRadiusGradientType kcrgt;
0144     return &kcrgt;
0145 }
0146 
0147 KalziumCovalentRadiusGradientType::KalziumCovalentRadiusGradientType()
0148     : KalziumGradientType()
0149 {
0150 }
0151 
0152 QByteArray KalziumCovalentRadiusGradientType::name() const
0153 {
0154     return "CovalentRadius";
0155 }
0156 
0157 QString KalziumCovalentRadiusGradientType::description() const
0158 {
0159     return i18n("Covalent Radius");
0160 }
0161 
0162 double KalziumCovalentRadiusGradientType::value(int el) const
0163 {
0164     QVariant v = KalziumDataObject::instance()->element(el)->dataAsVariant(ChemicalDataObject::radiusCovalent, Prefs::lengthUnit());
0165     if (v.type() != QVariant::Double)
0166         return -1;
0167     return v.toDouble();
0168 }
0169 
0170 QString KalziumCovalentRadiusGradientType::unit() const
0171 {
0172     return KalziumDataObject::instance()->unitAsString(Prefs::lengthUnit());
0173 }
0174 
0175 int KalziumCovalentRadiusGradientType::decimals() const
0176 {
0177     return 2;
0178 }
0179 
0180 double KalziumCovalentRadiusGradientType::minValue() const
0181 {
0182     KUnitConversion::Value minValue(0.32, KUnitConversion::Angstrom);
0183     return minValue.convertTo(KUnitConversion::UnitId(Prefs::lengthUnit())).number();
0184 }
0185 
0186 double KalziumCovalentRadiusGradientType::maxValue() const
0187 {
0188     KUnitConversion::Value minValue(2.25, KUnitConversion::Angstrom);
0189     return minValue.convertTo(KUnitConversion::UnitId(Prefs::lengthUnit())).number();
0190 }
0191 
0192 bool KalziumCovalentRadiusGradientType::logarithmicGradient() const
0193 {
0194     return Prefs::logarithmicCovalentRadiusGradient();
0195 }
0196 
0197 KalziumVanDerWaalsRadiusGradientType *KalziumVanDerWaalsRadiusGradientType::instance()
0198 {
0199     static KalziumVanDerWaalsRadiusGradientType kvdwrgt;
0200     return &kvdwrgt;
0201 }
0202 
0203 KalziumVanDerWaalsRadiusGradientType::KalziumVanDerWaalsRadiusGradientType()
0204     : KalziumGradientType()
0205 {
0206 }
0207 
0208 QByteArray KalziumVanDerWaalsRadiusGradientType::name() const
0209 {
0210     return "KalziumVanDerWaalsRadiusGradientType";
0211 }
0212 
0213 QString KalziumVanDerWaalsRadiusGradientType::description() const
0214 {
0215     return i18n("Van Der Waals");
0216 }
0217 
0218 double KalziumVanDerWaalsRadiusGradientType::value(int el) const
0219 {
0220     QVariant v = KalziumDataObject::instance()->element(el)->dataAsVariant(ChemicalDataObject::radiusVDW, Prefs::lengthUnit());
0221     if (v.type() != QVariant::Double)
0222         return -1;
0223     return v.toDouble();
0224 }
0225 
0226 QString KalziumVanDerWaalsRadiusGradientType::unit() const
0227 {
0228     return KalziumDataObject::instance()->unitAsString(Prefs::lengthUnit());
0229 }
0230 
0231 int KalziumVanDerWaalsRadiusGradientType::decimals() const
0232 {
0233     return 1;
0234 }
0235 
0236 double KalziumVanDerWaalsRadiusGradientType::minValue() const
0237 {
0238     KUnitConversion::Value minValue(1.2, KUnitConversion::Angstrom);
0239     return minValue.convertTo(KUnitConversion::UnitId(Prefs::lengthUnit())).number();
0240 }
0241 
0242 double KalziumVanDerWaalsRadiusGradientType::maxValue() const
0243 {
0244     KUnitConversion::Value minValue(3.0, KUnitConversion::Angstrom);
0245     return minValue.convertTo(KUnitConversion::UnitId(Prefs::lengthUnit())).number();
0246 }
0247 
0248 bool KalziumVanDerWaalsRadiusGradientType::logarithmicGradient() const
0249 {
0250     return Prefs::logarithmicVanDerWaalsRadiusGradient();
0251 }
0252 
0253 KalziumMassGradientType *KalziumMassGradientType::instance()
0254 {
0255     static KalziumMassGradientType kargt;
0256     return &kargt;
0257 }
0258 
0259 KalziumMassGradientType::KalziumMassGradientType()
0260     : KalziumGradientType()
0261 {
0262 }
0263 
0264 QByteArray KalziumMassGradientType::name() const
0265 {
0266     return "AtomicMass";
0267 }
0268 
0269 QString KalziumMassGradientType::description() const
0270 {
0271     return i18n("Atomic Mass");
0272 }
0273 
0274 double KalziumMassGradientType::value(int el) const
0275 {
0276     QVariant v = KalziumDataObject::instance()->element(el)->dataAsVariant(ChemicalDataObject::mass);
0277     if (v.type() != QVariant::Double)
0278         return -1;
0279     return v.toDouble();
0280 }
0281 
0282 QString KalziumMassGradientType::unit() const
0283 {
0284     return i18n("u");
0285 }
0286 
0287 int KalziumMassGradientType::decimals() const
0288 {
0289     return 5;
0290 }
0291 
0292 double KalziumMassGradientType::minValue() const
0293 {
0294     return 1.00794;
0295 }
0296 
0297 double KalziumMassGradientType::maxValue() const
0298 {
0299     return 294.0;
0300 }
0301 
0302 bool KalziumMassGradientType::logarithmicGradient() const
0303 {
0304     return Prefs::logarithmicMassGradient();
0305 }
0306 
0307 KalziumBoilingPointGradientType *KalziumBoilingPointGradientType::instance()
0308 {
0309     static KalziumBoilingPointGradientType kbpgt;
0310     return &kbpgt;
0311 }
0312 
0313 KalziumBoilingPointGradientType::KalziumBoilingPointGradientType()
0314     : KalziumGradientType()
0315 {
0316 }
0317 
0318 QByteArray KalziumBoilingPointGradientType::name() const
0319 {
0320     return "BoilingPoint";
0321 }
0322 
0323 QString KalziumBoilingPointGradientType::description() const
0324 {
0325     return i18n("Boiling Point");
0326 }
0327 
0328 double KalziumBoilingPointGradientType::value(int el) const
0329 {
0330     QVariant v = KalziumDataObject::instance()->element(el)->dataAsVariant(ChemicalDataObject::boilingpoint, Prefs::temperatureUnit());
0331     if (v.type() != QVariant::Double)
0332         return -1;
0333     return v.toDouble();
0334 }
0335 
0336 QString KalziumBoilingPointGradientType::unit() const
0337 {
0338     return KalziumDataObject::instance()->unitAsString(Prefs::temperatureUnit());
0339 }
0340 
0341 int KalziumBoilingPointGradientType::decimals() const
0342 {
0343     return 3;
0344 }
0345 
0346 double KalziumBoilingPointGradientType::minValue() const
0347 {
0348     KUnitConversion::Value minValue(4.216, KUnitConversion::Kelvin);
0349     return minValue.convertTo(KUnitConversion::UnitId(Prefs::temperatureUnit())).number();
0350 }
0351 
0352 double KalziumBoilingPointGradientType::maxValue() const
0353 {
0354     KUnitConversion::Value minValue(5870.0, KUnitConversion::Kelvin);
0355     return minValue.convertTo(KUnitConversion::UnitId(Prefs::temperatureUnit())).number();
0356 }
0357 
0358 bool KalziumBoilingPointGradientType::logarithmicGradient() const
0359 {
0360     return Prefs::logarithmicBoilingPointGradient();
0361 }
0362 
0363 KalziumMeltingPointGradientType *KalziumMeltingPointGradientType::instance()
0364 {
0365     static KalziumMeltingPointGradientType kmpgt;
0366     return &kmpgt;
0367 }
0368 
0369 KalziumMeltingPointGradientType::KalziumMeltingPointGradientType()
0370     : KalziumGradientType()
0371 {
0372 }
0373 
0374 QByteArray KalziumMeltingPointGradientType::name() const
0375 {
0376     return "MeltingPoint";
0377 }
0378 
0379 QString KalziumMeltingPointGradientType::description() const
0380 {
0381     return i18n("Melting Point");
0382 }
0383 
0384 double KalziumMeltingPointGradientType::value(int el) const
0385 {
0386     QVariant v = KalziumDataObject::instance()->element(el)->dataAsVariant(ChemicalDataObject::meltingpoint, Prefs::temperatureUnit());
0387     if (v.type() != QVariant::Double)
0388         return -1;
0389     return v.toDouble();
0390 }
0391 
0392 QString KalziumMeltingPointGradientType::unit() const
0393 {
0394     return KalziumDataObject::instance()->unitAsString(Prefs::temperatureUnit());
0395 }
0396 
0397 int KalziumMeltingPointGradientType::decimals() const
0398 {
0399     return 2;
0400 }
0401 
0402 double KalziumMeltingPointGradientType::minValue() const
0403 {
0404     KUnitConversion::Value minValue(0.94, KUnitConversion::Kelvin);
0405     return minValue.convertTo(KUnitConversion::UnitId(Prefs::temperatureUnit())).number();
0406 }
0407 
0408 double KalziumMeltingPointGradientType::maxValue() const
0409 {
0410     KUnitConversion::Value minValue(3825.0, KUnitConversion::Kelvin);
0411     return minValue.convertTo(KUnitConversion::UnitId(Prefs::temperatureUnit())).number();
0412 }
0413 
0414 bool KalziumMeltingPointGradientType::logarithmicGradient() const
0415 {
0416     return Prefs::logarithmicMeltingPointGradient();
0417 }
0418 
0419 KalziumSOMGradientType *KalziumSOMGradientType::instance()
0420 {
0421     static KalziumSOMGradientType kargt;
0422     return &kargt;
0423 }
0424 
0425 KalziumSOMGradientType::KalziumSOMGradientType()
0426     : KalziumGradientType()
0427 {
0428 }
0429 
0430 QByteArray KalziumSOMGradientType::name() const
0431 {
0432     return "SOM";
0433 }
0434 
0435 QString KalziumSOMGradientType::description() const
0436 {
0437     return i18n("State of matter");
0438 }
0439 
0440 double KalziumSOMGradientType::value(int el) const
0441 {
0442     Q_UNUSED(el);
0443     return -1000;
0444 }
0445 
0446 QString KalziumSOMGradientType::unit() const
0447 {
0448     return KalziumDataObject::instance()->unitAsString(Prefs::temperatureUnit());
0449     ;
0450 }
0451 
0452 int KalziumSOMGradientType::decimals() const
0453 {
0454     return 2;
0455 }
0456 
0457 double KalziumSOMGradientType::minValue() const
0458 {
0459     KUnitConversion::Value minValue(0.94, KUnitConversion::Kelvin);
0460     return minValue.convertTo(KUnitConversion::UnitId(Prefs::temperatureUnit())).number();
0461 }
0462 
0463 double KalziumSOMGradientType::maxValue() const
0464 {
0465     KUnitConversion::Value minValue(5870.0, KUnitConversion::Kelvin);
0466     return minValue.convertTo(KUnitConversion::UnitId(Prefs::temperatureUnit())).number();
0467 }
0468 
0469 bool KalziumSOMGradientType::logarithmicGradient() const
0470 {
0471     return true;
0472     //     return Prefs::logarithmicSOMGradient();
0473 }
0474 
0475 KalziumElectronegativityGradientType *KalziumElectronegativityGradientType::instance()
0476 {
0477     static KalziumElectronegativityGradientType kegt;
0478     return &kegt;
0479 }
0480 
0481 KalziumElectronegativityGradientType::KalziumElectronegativityGradientType()
0482     : KalziumGradientType()
0483 {
0484 }
0485 
0486 QByteArray KalziumElectronegativityGradientType::name() const
0487 {
0488     return "Electronegativity";
0489 }
0490 
0491 QString KalziumElectronegativityGradientType::description() const
0492 {
0493     return i18n("Electronegativity (Pauling)");
0494 }
0495 
0496 double KalziumElectronegativityGradientType::value(int el) const
0497 {
0498     QVariant v = KalziumDataObject::instance()->element(el)->dataAsVariant(ChemicalDataObject::electronegativityPauling);
0499     if (v.type() != QVariant::Double)
0500         return -1;
0501     return v.toDouble();
0502 }
0503 
0504 QString KalziumElectronegativityGradientType::unit() const
0505 {
0506     return {};
0507 }
0508 
0509 int KalziumElectronaffinityGradientType::decimals() const
0510 {
0511     return 2;
0512 }
0513 
0514 double KalziumElectronegativityGradientType::minValue() const
0515 {
0516     return 0.7;
0517 }
0518 
0519 double KalziumElectronegativityGradientType::maxValue() const
0520 {
0521     return 3.98;
0522 }
0523 
0524 bool KalziumElectronegativityGradientType::logarithmicGradient() const
0525 {
0526     return Prefs::logarithmicElectronegativityGradient();
0527 }
0528 
0529 /// DISCOVERYDATE///
0530 
0531 KalziumDiscoverydateGradientType *KalziumDiscoverydateGradientType::instance()
0532 {
0533     static KalziumDiscoverydateGradientType kegt;
0534     return &kegt;
0535 }
0536 
0537 KalziumDiscoverydateGradientType::KalziumDiscoverydateGradientType()
0538     : KalziumGradientType()
0539 {
0540 }
0541 
0542 QByteArray KalziumDiscoverydateGradientType::name() const
0543 {
0544     return "Discoverydate";
0545 }
0546 
0547 QString KalziumDiscoverydateGradientType::description() const
0548 {
0549     return i18n("Discovery date");
0550 }
0551 
0552 double KalziumDiscoverydateGradientType::value(int el) const
0553 {
0554     QVariant v = KalziumDataObject::instance()->element(el)->dataAsVariant(ChemicalDataObject::date);
0555     if (v.value<int>() == 0)
0556         return -1;
0557     return v.toDouble();
0558 }
0559 
0560 QString KalziumDiscoverydateGradientType::unit() const
0561 {
0562     return {};
0563 }
0564 
0565 int KalziumDiscoverydateGradientType::decimals() const
0566 {
0567     return 0;
0568 }
0569 
0570 double KalziumDiscoverydateGradientType::minValue() const
0571 {
0572     return 1669.0;
0573 }
0574 
0575 double KalziumDiscoverydateGradientType::maxValue() const
0576 {
0577     return QDate::currentDate().year();
0578 }
0579 
0580 bool KalziumDiscoverydateGradientType::logarithmicGradient() const
0581 {
0582     return Prefs::logarithmicDiscoverydateGradient();
0583 }
0584 
0585 /// ELECTRONAFFINITY///
0586 
0587 KalziumElectronaffinityGradientType *KalziumElectronaffinityGradientType::instance()
0588 {
0589     static KalziumElectronaffinityGradientType kegt;
0590     return &kegt;
0591 }
0592 
0593 KalziumElectronaffinityGradientType::KalziumElectronaffinityGradientType()
0594     : KalziumGradientType()
0595 {
0596 }
0597 
0598 QByteArray KalziumElectronaffinityGradientType::name() const
0599 {
0600     return "Electronaffinity";
0601 }
0602 
0603 QString KalziumElectronaffinityGradientType::description() const
0604 {
0605     return i18n("Electronaffinity");
0606 }
0607 
0608 double KalziumElectronaffinityGradientType::value(int el) const
0609 {
0610     QVariant v = KalziumDataObject::instance()->element(el)->dataAsVariant(ChemicalDataObject::electronAffinity, Prefs::energiesUnit());
0611     return v.toDouble();
0612 }
0613 
0614 QString KalziumElectronaffinityGradientType::unit() const
0615 {
0616     return KalziumDataObject::instance()->unitAsString(Prefs::energiesUnit());
0617 }
0618 
0619 int KalziumElectronegativityGradientType::decimals() const
0620 {
0621     return 2;
0622 }
0623 
0624 double KalziumElectronaffinityGradientType::minValue() const
0625 {
0626     KUnitConversion::Value minValue(-0.07, KUnitConversion::Electronvolt);
0627     return minValue.convertTo(KUnitConversion::UnitId(Prefs::energiesUnit())).number();
0628 }
0629 
0630 double KalziumElectronaffinityGradientType::maxValue() const
0631 {
0632     KUnitConversion::Value minValue(3.7, KUnitConversion::Electronvolt);
0633     return minValue.convertTo(KUnitConversion::UnitId(Prefs::energiesUnit())).number();
0634 }
0635 
0636 bool KalziumElectronaffinityGradientType::logarithmicGradient() const
0637 {
0638     return Prefs::logarithmicElectronaffinityGradient();
0639 }
0640 
0641 /// FIRST IONIZATINO///
0642 
0643 KalziumIonizationGradientType *KalziumIonizationGradientType::instance()
0644 {
0645     static KalziumIonizationGradientType kegt;
0646     return &kegt;
0647 }
0648 
0649 KalziumIonizationGradientType::KalziumIonizationGradientType()
0650     : KalziumGradientType()
0651 {
0652 }
0653 
0654 QByteArray KalziumIonizationGradientType::name() const
0655 {
0656     return "Ionization";
0657 }
0658 
0659 QString KalziumIonizationGradientType::description() const
0660 {
0661     return i18n("First Ionization");
0662 }
0663 
0664 double KalziumIonizationGradientType::value(int el) const
0665 {
0666     QVariant v = KalziumDataObject::instance()->element(el)->dataAsVariant(ChemicalDataObject::ionization, Prefs::energiesUnit());
0667     return v.toDouble();
0668 }
0669 
0670 QString KalziumIonizationGradientType::unit() const
0671 {
0672     return KalziumDataObject::instance()->unitAsString(Prefs::energiesUnit());
0673 }
0674 
0675 int KalziumIonizationGradientType::decimals() const
0676 {
0677     return 2;
0678 }
0679 
0680 double KalziumIonizationGradientType::minValue() const
0681 {
0682     KUnitConversion::Value minValue(3.89, KUnitConversion::Electronvolt);
0683     return minValue.convertTo(KUnitConversion::UnitId(Prefs::energiesUnit())).number();
0684 }
0685 
0686 double KalziumIonizationGradientType::maxValue() const
0687 {
0688     KUnitConversion::Value minValue(25.0, KUnitConversion::Electronvolt);
0689     return minValue.convertTo(KUnitConversion::UnitId(Prefs::energiesUnit())).number();
0690 }
0691 
0692 bool KalziumIonizationGradientType::logarithmicGradient() const
0693 {
0694     return Prefs::logarithmicIonizationGradient();
0695 }