pythonforecast.cpp
Go to the documentation of this file.
00001 /*************************************************************************** 00002 file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/tags/0.9.1/modules/forecast/pythonforecast.cpp $ 00003 version : $LastChangedRevision: 1656 $ $LastChangedBy: jdetaeye $ 00004 date : $LastChangedDate: 2012-03-27 19:05:34 +0200 (Tue, 27 Mar 2012) $ 00005 ***************************************************************************/ 00006 00007 /*************************************************************************** 00008 * * 00009 * Copyright (C) 2007-2012 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, "dO|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 { 00146 // Generate the forecast 00147 forecast->generateFutureValues 00148 (data, historycount, bucketdata, bucketcount, true); 00149 } 00150 catch (...) 00151 { 00152 Py_BLOCK_THREADS; 00153 PythonType::evalException(); 00154 return NULL; 00155 } 00156 Py_END_ALLOW_THREADS // Release the Python interpreter 00157 return Py_BuildValue(""); 00158 } 00159 00160 00161 PyObject* ForecastBucket::getattro(const Attribute& attr) 00162 { 00163 if (attr.isA(Tags::tag_startdate)) 00164 return PythonObject(getDueRange().getStart()); 00165 if (attr.isA(Tags::tag_enddate)) 00166 return PythonObject(getDueRange().getEnd()); 00167 if (attr.isA(Forecast::tag_total)) 00168 return PythonObject(getTotal()); 00169 if (attr.isA(Forecast::tag_consumed)) 00170 return PythonObject(getConsumed()); 00171 if (attr.isA(Tags::tag_weight)) 00172 return PythonObject(getWeight()); 00173 return Demand::getattro(attr); 00174 } 00175 00176 00177 int ForecastBucket::setattro(const Attribute& attr, const PythonObject& field) 00178 { 00179 if (attr.isA(Forecast::tag_total)) 00180 setTotal(field.getDouble()); 00181 else if (attr.isA(Forecast::tag_consumed)) 00182 setConsumed(field.getDouble()); 00183 else if (attr.isA(Tags::tag_weight)) 00184 setWeight(field.getDouble()); 00185 else 00186 return Demand::setattro(attr, field); 00187 return 0; // OK 00188 } 00189 00190 00191 } // end namespace