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

Documentation generated for frePPLe by  doxygen