pythonforecast.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002   file : $URL: http://svn.code.sf.net/p/frepple/code/trunk/modules/forecast/pythonforecast.cpp $
00003   version : $LastChangedRevision: 1713 $  $LastChangedBy: jdetaeye $
00004   date : $LastChangedDate: 2012-07-18 11:46:01 +0200 (Wed, 18 Jul 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 Affero General Public License as published   *
00013  * by the Free Software Foundation; either version 3 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            *
00019  * GNU Affero General Public License for more details.                     *
00020  *                                                                         *
00021  * You should have received a copy of the GNU Affero General Public        *
00022  * License along with this program.                                        *
00023  * If not, see <http://www.gnu.org/licenses/>.                             *
00024  *                                                                         *
00025  ***************************************************************************/
00026 
00027 #include "forecast.h"
00028 
00029 namespace module_forecast
00030 {
00031 
00032 
00033 PyObject* Forecast::getattro(const Attribute& attr)
00034 {
00035   if (attr.isA(Tags::tag_calendar))
00036     return PythonObject(getCalendar());
00037   else if (attr.isA(Tags::tag_discrete))
00038     return PythonObject(getDiscrete());
00039   return Demand::getattro(attr);
00040 }
00041 
00042 
00043 int Forecast::setattro(const Attribute& attr, const PythonObject& field)
00044 {
00045   if (attr.isA(Tags::tag_calendar))
00046   {
00047     if (!field.check(Calendar::metadata))
00048     {
00049       PyErr_SetString(PythonDataException, "forecast calendar must be of type calendar");
00050       return -1;
00051     }
00052     Calendar* y = static_cast<Calendar*>(static_cast<PyObject*>(field));
00053     setCalendar(y);
00054   }
00055   else if (attr.isA(Tags::tag_discrete))
00056     setDiscrete(field.getBool());
00057   else
00058     return Demand::setattro(attr, field);
00059   return 0; // OK
00060 }
00061 
00062 
00063 extern "C" PyObject* Forecast::setPythonTotalQuantity(PyObject *self, PyObject *args)
00064 {
00065   try
00066   {
00067     // Get the forecast model
00068     Forecast* forecast = static_cast<Forecast*>(self);
00069 
00070     // Parse the Python arguments
00071     double value;
00072     PyObject* pystart;
00073     PyObject* pyend = NULL;
00074     int ok = PyArg_ParseTuple(args, "dO|O:setQuantity", &value, &pystart, &pyend);
00075     if (!ok) return NULL;
00076 
00077     // Update the forecast
00078     PythonObject start(pystart), end(pyend);
00079     if (pyend)
00080       forecast->setTotalQuantity(DateRange(start.getDate(), end.getDate()), value);
00081     else
00082       forecast->setTotalQuantity(start.getDate(), value);
00083   }
00084   catch(...)
00085   {
00086     PythonType::evalException();
00087     return NULL;
00088   }
00089   return Py_BuildValue("");
00090 }
00091 
00092 
00093 extern "C" PyObject* Forecast::timeseries(PyObject *self, PyObject *args)
00094 {
00095   // Get the forecast model
00096   Forecast* forecast = static_cast<Forecast*>(self);
00097 
00098   // Parse the Python arguments
00099   PyObject* history;
00100   PyObject* buckets = NULL;
00101   int ok = PyArg_ParseTuple(args, "O|O:timeseries", &history, &buckets);
00102   if (!ok) return NULL;
00103 
00104   // Verify we can iterate over the arguments
00105   PyObject *historyiterator = PyObject_GetIter(history);
00106   PyObject *bucketiterator = NULL;
00107   if (!historyiterator)
00108   {
00109     PyErr_Format(PyExc_AttributeError,"Invalid type for time series");
00110     return NULL;
00111   }
00112   if (buckets) bucketiterator = PyObject_GetIter(buckets);
00113   if (!bucketiterator)
00114   {
00115     PyErr_Format(PyExc_AttributeError,"Invalid type for time series");
00116     return NULL;
00117   }
00118 
00119   // Copy the history data into a C++ data structure
00120   double data[300];
00121   unsigned int historycount = 0;
00122   PyObject *item;
00123   while ((item = PyIter_Next(historyiterator)))
00124   {
00125     data[historycount++] = PyFloat_AsDouble(item);
00126     Py_DECREF(item);
00127     if (historycount>=300) break;
00128   }
00129   Py_DECREF(historyiterator);
00130 
00131   // Copy the bucket data into a C++ data structure
00132   Date bucketdata[300];
00133   unsigned int bucketcount = 0;
00134   while ((item = PyIter_Next(bucketiterator)))
00135   {
00136     bucketdata[bucketcount++] = PythonObject(item).getDate();
00137     Py_DECREF(item);
00138     if (bucketcount>=300) break;
00139   }
00140   Py_DECREF(bucketiterator);
00141 
00142   Py_BEGIN_ALLOW_THREADS  // Free the Python interpreter for other threads
00143   try
00144   {
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

Documentation generated for frePPLe by  doxygen