File indexing completed on 2023-05-30 09:03:12
0001 /* 0002 SPDX-License-Identifier: GPL-2.0-or-later 0003 SPDX-FileCopyrightText: 2013 Filipe Saraiva <filipe@kde.org> 0004 */ 0005 0006 #include "pythonextensions.h" 0007 0008 #include <QDebug> 0009 0010 #include <KLocalizedString> 0011 0012 #include "pythonutils.h" 0013 0014 #include "settings.h" 0015 0016 #define PYTHON_EXT_CDTOR(name) Python##name##Extension::Python##name##Extension(QObject* parent) : name##Extension(parent) {} \ 0017 Python##name##Extension::~Python##name##Extension() {} 0018 0019 PYTHON_EXT_CDTOR(LinearAlgebra) 0020 0021 QString PythonLinearAlgebraExtension::createVector(const QStringList& entries, Cantor::LinearAlgebraExtension::VectorType type) 0022 { 0023 Q_UNUSED(type); 0024 0025 QString command; 0026 command += QLatin1String("numpy.matrix(["); 0027 0028 foreach (const QString& entry, entries) 0029 { 0030 command += entry + QLatin1String(", "); 0031 } 0032 0033 command.chop(2); 0034 command += QLatin1String("])\n"); 0035 0036 return command; 0037 } 0038 0039 QString PythonLinearAlgebraExtension::createMatrix(const Cantor::LinearAlgebraExtension::Matrix& matrix) 0040 { 0041 QString command; 0042 command += QLatin1String("numpy.matrix([["); 0043 0044 foreach (const QStringList row, matrix) 0045 { 0046 foreach (const QString entry, row) 0047 { 0048 command += entry; 0049 command += QLatin1String(", "); 0050 } 0051 command.chop(2); 0052 command += QLatin1String("], ["); 0053 } 0054 0055 command.chop(3); 0056 command += QLatin1String("])"); 0057 0058 return command; 0059 } 0060 0061 QString PythonLinearAlgebraExtension::eigenValues(const QString& matrix) 0062 { 0063 return QString::fromLatin1("numpy.linalg.eigvals(%1)").arg(matrix); 0064 } 0065 0066 QString PythonLinearAlgebraExtension::eigenVectors(const QString& matrix) 0067 { 0068 return QString::fromLatin1("numpy.linalg.eig(%1)").arg(matrix); 0069 } 0070 0071 QString PythonLinearAlgebraExtension::identityMatrix(int size) 0072 { 0073 return QString::fromLatin1("numpy.identity(%1)").arg(size); 0074 } 0075 0076 QString PythonLinearAlgebraExtension::invertMatrix(const QString& matrix) 0077 { 0078 return QString::fromLatin1("numpy.linalg.inv(%1)").arg(matrix); 0079 } 0080 0081 QString PythonLinearAlgebraExtension::nullMatrix(int rows, int columns) 0082 { 0083 return QString::fromLatin1("numpy.zeros(%1, %2)").arg(rows).arg(columns); 0084 } 0085 0086 QString PythonLinearAlgebraExtension::nullVector(int size, Cantor::LinearAlgebraExtension::VectorType type) 0087 { 0088 QString command = QLatin1String("numpy.zeros(%1, %2)"); 0089 switch (type) 0090 { 0091 case ColumnVector: 0092 return command.arg(size).arg(1); 0093 case RowVector: 0094 return command.arg(1).arg(size); 0095 default: 0096 return Cantor::LinearAlgebraExtension::nullVector(size, type); 0097 } 0098 } 0099 0100 QString PythonLinearAlgebraExtension::rank(const QString& matrix) 0101 { 0102 return QString::fromLatin1("numpy.linalg.matrix_rank(%1)").arg(matrix); 0103 } 0104 0105 QString PythonLinearAlgebraExtension::charPoly(const QString& matrix) 0106 { 0107 return QString::fromLatin1("numpy.poly(%1)").arg(matrix); 0108 } 0109 0110 PYTHON_EXT_CDTOR(Packaging) 0111 0112 QString PythonPackagingExtension::importPackage(const QString& package) 0113 { 0114 return QString::fromLatin1("import %1").arg(package); 0115 } 0116 0117 PYTHON_EXT_CDTOR(Plot) 0118 0119 QString PythonPlotExtension::plotFunction2d(const QString& function, const QString& variable, const QString& left, const QString& right) 0120 { 0121 QString command; 0122 QString limits; 0123 0124 int val = PythonSettings::plotExtenstionGraphicPackage(); 0125 switch (val) 0126 { 0127 case PythonSettings::EnumPlotExtenstionGraphicPackage::matplotlib: 0128 if (!left.isEmpty() && !right.isEmpty()) 0129 limits = QString::fromLatin1("plt.xlim(%1, %2)\n").arg(left, right); 0130 command = QString::fromLatin1( 0131 "import matplotlib.pyplot as plt\n" 0132 "\n" 0133 "plt.plot(%1, %2)\n" 0134 "%3" 0135 "plt.show()" 0136 ).arg(variable, function, limits); 0137 break; 0138 0139 case PythonSettings::EnumPlotExtenstionGraphicPackage::pylab: 0140 if (!left.isEmpty() && !right.isEmpty()) 0141 limits = QString::fromLatin1("pylab.xlim(%1, %2)\n").arg(left, right); 0142 command = QString::fromLatin1( 0143 "import pylab\n" 0144 "\n" 0145 "pylab.clf()\n" 0146 "pylab.plot(%1, %2)\n" 0147 "%3" 0148 "pylab.show()" 0149 ).arg(variable, function, limits); 0150 break; 0151 0152 case PythonSettings::EnumPlotExtenstionGraphicPackage::plotly: 0153 if (!left.isEmpty() && !right.isEmpty()) 0154 limits = QString::fromLatin1("fig.update_layout(xaxis=dict(range=[%1, %2]))\n").arg(left, right); 0155 command = QString::fromLatin1( 0156 "import plotly.graph_objects as go\n" 0157 "\n" 0158 "fig = go.Figure(data=go.Scatter(x=%1, y=%2))\n" 0159 "%3" 0160 "fig.show()" 0161 ).arg(variable, function, limits); 0162 break; 0163 0164 case PythonSettings::EnumPlotExtenstionGraphicPackage::gr: 0165 if (!left.isEmpty() && !right.isEmpty()) 0166 limits = QString::fromLatin1("\nmlab.xlim(%1, %2)").arg(left, right); 0167 command = QString::fromLatin1( 0168 "from gr.pygr import mlab\n" 0169 "\n" 0170 "mlab.plot(%1, %2)" 0171 "%3" 0172 ).arg(variable, function, limits); 0173 break; 0174 0175 case PythonSettings::EnumPlotExtenstionGraphicPackage::bokeh: 0176 if (!left.isEmpty() && !right.isEmpty()) 0177 limits = QString::fromLatin1("x_range=(%1, %2)").arg(left, right); 0178 command = QString::fromLatin1( 0179 "from bokeh.plotting import figure, show\n" 0180 "\n" 0181 "fig = figure(%3)\n" 0182 "fig.line(%1, %2)\n" 0183 "show(fig)" 0184 ).arg(variable, function, limits); 0185 break; 0186 }; 0187 0188 return command; 0189 } 0190 0191 QString PythonPlotExtension::plotFunction3d(const QString& function, const VariableParameter& var1, const VariableParameter& var2) 0192 { 0193 QString command; 0194 0195 const Interval& interval1 = var1.second; 0196 const Interval& interval2 = var2.second; 0197 0198 QString interval1Limits; 0199 QString interval2Limits; 0200 0201 int val = PythonSettings::plotExtenstionGraphicPackage(); 0202 switch (val) 0203 { 0204 case PythonSettings::EnumPlotExtenstionGraphicPackage::matplotlib: 0205 if(!interval1.first.isEmpty() && !interval1.second.isEmpty()){ 0206 interval1Limits = QString::fromLatin1("ax3D.set_xlim3d(%1, %2)\n").arg(interval1.first, interval1.second); 0207 } 0208 0209 if(!interval2.first.isEmpty() && !interval2.second.isEmpty()){ 0210 interval2Limits = QString::fromLatin1("ax3D.set_ylim3d(%1, %2)\n").arg(interval2.first, interval2.second); 0211 } 0212 0213 command = QString::fromLatin1( 0214 "import matplotlib.pyplot as plt\n" 0215 "from mpl_toolkits.mplot3d import Axes3D\n\n" 0216 "fig3D = plt.figure()\n" 0217 "ax3D = fig3D.gca(projection='3d')\n" 0218 "ax3D.plot_surface(%1, %2, %3)\n" \ 0219 "%4%5" \ 0220 "plt.show()" 0221 ).arg(var1.first, var2.first, function, interval1Limits, interval2Limits); 0222 break; 0223 0224 case PythonSettings::EnumPlotExtenstionGraphicPackage::pylab: 0225 if(!interval1.first.isEmpty() && !interval1.second.isEmpty()){ 0226 interval1Limits = QString::fromLatin1("ax3D.set_xlim3d(%1, %2)\n").arg(interval1.first, interval1.second); 0227 } 0228 0229 if(!interval2.first.isEmpty() && !interval2.second.isEmpty()){ 0230 interval2Limits = QString::fromLatin1("ax3D.set_ylim3d(%1, %2)\n").arg(interval2.first, interval2.second); 0231 } 0232 0233 command = QString::fromLatin1( 0234 "import pylab\n" 0235 "from mpl_toolkits.mplot3d import Axes3D\n\n" 0236 "fig3D = pylab.figure()\n" 0237 "ax3D = fig3D.gca(projection='3d')\n" 0238 "ax3D.plot_surface(%1, %2, %3)\n" \ 0239 "%4%5" \ 0240 "pylab.show()" 0241 ).arg(var1.first, var2.first, function, interval1Limits, interval2Limits); 0242 break; 0243 0244 case PythonSettings::EnumPlotExtenstionGraphicPackage::plotly: 0245 if(!interval1.first.isEmpty() && !interval1.second.isEmpty()){ 0246 interval1Limits = QString::fromLatin1("fig.update_layout(xaxis=dict(range=[%1, %2]))\n").arg(interval1.first, interval1.second); 0247 } 0248 0249 if(!interval2.first.isEmpty() && !interval2.second.isEmpty()){ 0250 interval2Limits = QString::fromLatin1("fig.update_layout(yaxis=dict(range=[%1, %2]))\n").arg(interval2.first, interval2.second); 0251 } 0252 0253 command = QString::fromLatin1( 0254 "import plotly.graph_objects as go\n" 0255 "\n" 0256 "fig = go.Figure(data=go.Scatter3d(x=%1, y=%2, z=%3))\n" 0257 "%4%5" 0258 "fig.show()" 0259 ).arg(var1.first, var2.first, function, interval1Limits, interval2Limits); 0260 break; 0261 0262 case PythonSettings::EnumPlotExtenstionGraphicPackage::gr: 0263 { 0264 if(!interval1.first.isEmpty() && !interval1.second.isEmpty()){ 0265 interval1Limits = QString::fromLatin1("mlab.xlim(%1, %2)\n").arg(interval1.first, interval1.second); 0266 } 0267 0268 if(!interval2.first.isEmpty() && !interval2.second.isEmpty()){ 0269 interval2Limits = QString::fromLatin1("mlab.ylim(%1, %2)").arg(interval2.first, interval2.second); 0270 } 0271 QString newLinePlacement; 0272 if(!interval1Limits.isEmpty() || !interval2Limits.isEmpty()) 0273 newLinePlacement = QLatin1String("\n"); 0274 0275 command = QString::fromLatin1( 0276 "from gr.pygr import mlab\n" 0277 "\n" 0278 "mlab.plot3(%1, %2, %3)%6" 0279 "%4%5" 0280 ).arg(var1.first, var2.first, function, interval1Limits, interval2Limits, newLinePlacement); 0281 } 0282 break; 0283 0284 case PythonSettings::EnumPlotExtenstionGraphicPackage::bokeh: 0285 command = i18n("# Sorry, but Bokeh doesn't support 3d plotting"); 0286 break; 0287 }; 0288 0289 return command; 0290 } 0291 0292 PYTHON_EXT_CDTOR(Script) 0293 0294 QString PythonScriptExtension::runExternalScript(const QString& path) 0295 { 0296 return QString::fromLatin1("exec(open(\"%1\").read())").arg(path); 0297 } 0298 0299 QString PythonScriptExtension::scriptFileFilter() 0300 { 0301 return i18n("Python script file (*.py)"); 0302 } 0303 0304 QString PythonScriptExtension::highlightingMode() 0305 { 0306 return QLatin1String("python"); 0307 } 0308 0309 PYTHON_EXT_CDTOR(VariableManagement) 0310 0311 QString PythonVariableManagementExtension::addVariable(const QString& name, const QString& value) 0312 { 0313 return setValue(name, value); 0314 } 0315 0316 QString PythonVariableManagementExtension::setValue(const QString& name, const QString& value) 0317 { 0318 return QString::fromLatin1("%1 = %2").arg(name, value); 0319 } 0320 0321 QString PythonVariableManagementExtension::removeVariable(const QString& name) 0322 { 0323 return QString::fromLatin1("del(%1)").arg(name); 0324 } 0325 0326 QString PythonVariableManagementExtension::clearVariables() 0327 { 0328 return fromSource(QLatin1String(":/py/variables_cleaner.py")); 0329 } 0330 0331 QString PythonVariableManagementExtension::saveVariables(const QString& fileName) 0332 { 0333 return fromSource(QLatin1String(":/py/variables_saver.py")).arg(fileName); 0334 } 0335 0336 QString PythonVariableManagementExtension::loadVariables(const QString& fileName) 0337 { 0338 return fromSource(QLatin1String(":/py/variables_loader.py")).arg(fileName); 0339 }