pythonforecast.cpp
Go to the documentation of this file.
00001 /*************************************************************************** 00002 file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/trunk/modules/forecast/pythonforecast.cpp $ 00003 version : $LastChangedRevision: 1508 $ $LastChangedBy: jdetaeye $ 00004 date : $LastChangedDate: 2011-09-10 10:53:11 +0200 (Sat, 10 Sep 2011) $ 00005 ***************************************************************************/ 00006 00007 /*************************************************************************** 00008 * * 00009 * Copyright (C) 2007-2011 by Johan De Taeye, frePPLe bvba * 00010 * * 00011 * This library is free software; you can redistribute it and/or modify it * 00012 * under the terms of the GNU Lesser General Public License as published * 00013 * by the Free Software Foundation; either version 2.1 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 * This library is distributed in the hope that it will be useful, * 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * 00019 * General Public License for more details. * 00020 * * 00021 * You should have received a copy of the GNU Lesser General Public * 00022 * License along with this library; if not, write to the Free Software * 00023 * Foundation Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * 00024 * USA * 00025 * * 00026 ***************************************************************************/ 00027 00028 #include "forecast.h" 00029 00030 namespace module_forecast 00031 { 00032 00033 00034 PyObject* Forecast::getattro(const Attribute& attr) 00035 { 00036 if (attr.isA(Tags::tag_calendar)) 00037 return PythonObject(getCalendar()); 00038 else if (attr.isA(Tags::tag_discrete)) 00039 return PythonObject(getDiscrete()); 00040 return Demand::getattro(attr); 00041 } 00042 00043 00044 int Forecast::setattro(const Attribute& attr, const PythonObject& field) 00045 { 00046 if (attr.isA(Tags::tag_calendar)) 00047 { 00048 if (!field.check(Calendar::metadata)) 00049 { 00050 PyErr_SetString(PythonDataException, "forecast calendar must be of type calendar"); 00051 return -1; 00052 } 00053 Calendar* y = static_cast<Calendar*>(static_cast<PyObject*>(field)); 00054 setCalendar(y); 00055 } 00056 else if (attr.isA(Tags::tag_discrete)) 00057 setDiscrete(field.getBool()); 00058 else 00059 return Demand::setattro(attr, field); 00060 return 0; // OK 00061 } 00062 00063 00064 extern "C" PyObject* Forecast::setPythonTotalQuantity(PyObject *self, PyObject *args) 00065 { 00066 try 00067 { 00068 // Get the forecast model 00069 Forecast* forecast = static_cast<Forecast*>(self); 00070 00071 // Parse the Python arguments 00072 double value; 00073 PyObject* pystart; 00074 PyObject* pyend = NULL; 00075 int ok = PyArg_ParseTuple(args, "fO|O:setQuantity", &value, &pystart, &pyend); 00076 if (!ok) return NULL; 00077 00078 // Update the forecast 00079 PythonObject start(pystart), end(pyend); 00080 if (pyend) 00081 forecast->setTotalQuantity(DateRange(start.getDate(), end.getDate()), value); 00082 else 00083 forecast->setTotalQuantity(start.getDate(), value); 00084 } 00085 catch(...) 00086 { 00087 PythonType::evalException(); 00088 return NULL; 00089 } 00090 return Py_BuildValue(""); 00091 } 00092 00093 00094 extern "C" PyObject* Forecast::timeseries(PyObject *self, PyObject *args) 00095 { 00096 // Get the forecast model 00097 Forecast* forecast = static_cast<Forecast*>(self); 00098 00099 // Parse the Python arguments 00100 PyObject* history; 00101 PyObject* buckets = NULL; 00102 int ok = PyArg_ParseTuple(args, "O|O:timeseries", &history, &buckets); 00103 if (!ok) return NULL; 00104 00105 // Verify we can iterate over the arguments 00106 PyObject *historyiterator = PyObject_GetIter(history); 00107 PyObject *bucketiterator = NULL; 00108 if (!historyiterator) 00109 { 00110 PyErr_Format(PyExc_AttributeError,"Invalid type for time series"); 00111 return NULL; 00112 } 00113 if (buckets) bucketiterator = PyObject_GetIter(buckets); 00114 if (!bucketiterator) 00115 { 00116 PyErr_Format(PyExc_AttributeError,"Invalid type for time series"); 00117 return NULL; 00118 } 00119 00120 // Copy the history data into a C++ data structure 00121 double data[300]; 00122 unsigned int historycount = 0; 00123 PyObject *item; 00124 while ((item = PyIter_Next(historyiterator))) 00125 { 00126 data[historycount++] = PyFloat_AsDouble(item); 00127 Py_DECREF(item); 00128 if (historycount>=300) break; 00129 } 00130 Py_DECREF(historyiterator); 00131 00132 // Copy the bucket data into a C++ data structure 00133 Date bucketdata[300]; 00134 unsigned int bucketcount = 0; 00135 while ((item = PyIter_Next(bucketiterator))) 00136 { 00137 bucketdata[bucketcount++] = PythonObject(item).getDate(); 00138 Py_DECREF(item); 00139 if (bucketcount>=300) break; 00140 } 00141 Py_DECREF(bucketiterator); 00142 00143 Py_BEGIN_ALLOW_THREADS // Free the Python interpreter for other threads 00144 try { 00145 // Generate the forecast 00146 forecast->generateFutureValues 00147 (data, historycount, bucketdata, bucketcount, true); 00148 } 00149 catch (...) 00150 { 00151 Py_BLOCK_THREADS; 00152 PythonType::evalException(); 00153 return NULL; 00154 } 00155 Py_END_ALLOW_THREADS // Release the Python interpreter 00156 return Py_BuildValue(""); 00157 } 00158 00159 00160 PyObject* ForecastBucket::getattro(const Attribute& attr) 00161 { 00162 if (attr.isA(Tags::tag_startdate)) 00163 return PythonObject(getDueRange().getStart()); 00164 if (attr.isA(Tags::tag_enddate)) 00165 return PythonObject(getDueRange().getEnd()); 00166 if (attr.isA(Forecast::tag_total)) 00167 return PythonObject(getTotal()); 00168 if (attr.isA(Forecast::tag_consumed)) 00169 return PythonObject(getConsumed()); 00170 if (attr.isA(Tags::tag_weight)) 00171 return PythonObject(getWeight()); 00172 return Demand::getattro(attr); 00173 } 00174 00175 00176 int ForecastBucket::setattro(const Attribute& attr, const PythonObject& field) 00177 { 00178 if (attr.isA(Forecast::tag_total)) 00179 setTotal(field.getDouble()); 00180 else if (attr.isA(Forecast::tag_consumed)) 00181 setConsumed(field.getDouble()); 00182 else if (attr.isA(Tags::tag_weight)) 00183 setWeight(field.getDouble()); 00184 else 00185 return Demand::setattro(attr, field); 00186 return 0; // OK 00187 } 00188 00189 00190 } // end namespace