pythonforecast.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002   file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/tags/0.8.0/modules/forecast/pythonforecast.cpp $
00003   version : $LastChangedRevision: 1108 $  $LastChangedBy: jdetaeye $
00004   date : $LastChangedDate: 2009-12-06 18:54:18 +0100 (Sun, 06 Dec 2009) $
00005  ***************************************************************************/
00006 
00007 /***************************************************************************
00008  *                                                                         *
00009  * Copyright (C) 2007 by Johan De Taeye                                    *
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::timeseries(PyObject *self, PyObject *args)
00065 {
00066   // Get the forecast model
00067   Forecast* forecast = static_cast<Forecast*>(self);
00068 
00069   // Parse the Python arguments
00070   PyObject* history;
00071   PyObject* buckets = NULL;
00072   int ok = PyArg_ParseTuple(args, "O|O", &history, &buckets);
00073   if (!ok) return NULL;
00074 
00075   // Verify we can iterate over the arguments
00076   PyObject *historyiterator = PyObject_GetIter(history);
00077   PyObject *bucketiterator = NULL;
00078   if (!historyiterator)
00079   {
00080     PyErr_Format(PyExc_AttributeError,"Invalid type for time series");
00081     return NULL;
00082   }
00083   if (buckets) bucketiterator = PyObject_GetIter(buckets);
00084   if (!bucketiterator)
00085   {
00086     PyErr_Format(PyExc_AttributeError,"Invalid type for time series");
00087     return NULL;
00088   }
00089 
00090   // Copy the history data into a C++ data structure
00091   double data[300];
00092   unsigned int historycount = 0;
00093   PyObject *item;
00094   while ((item = PyIter_Next(historyiterator)))
00095   {
00096     data[historycount++] = PyFloat_AsDouble(item);
00097     Py_DECREF(item);
00098     if (historycount>=300) break;
00099   }
00100   Py_DECREF(historyiterator);
00101 
00102   // Copy the bucket data into a C++ data structure
00103   Date bucketdata[300];
00104   unsigned int bucketcount = 0;
00105   while ((item = PyIter_Next(bucketiterator)))
00106   {
00107     bucketdata[bucketcount++] = PythonObject(item).getDate();
00108     Py_DECREF(item);
00109     if (bucketcount>=300) break;
00110   }
00111   Py_DECREF(bucketiterator);
00112 
00113   Py_BEGIN_ALLOW_THREADS  // Free the Python interpreter for other threads
00114   try {
00115     // Generate the forecast
00116     forecast->generateFutureValues
00117       (data, historycount, bucketdata, bucketcount, true);
00118   }
00119   catch (...)
00120   {
00121     Py_BLOCK_THREADS;
00122     PythonType::evalException();
00123     return NULL;
00124   }
00125   Py_END_ALLOW_THREADS   // Release the Python interpreter
00126   return Py_BuildValue("");
00127 }
00128 
00129 PyObject* ForecastBucket::getattro(const Attribute& attr)
00130 {
00131   if (attr.isA(Tags::tag_startdate))
00132     return PythonObject(getDueRange().getStart());
00133   if (attr.isA(Tags::tag_enddate))
00134     return PythonObject(getDueRange().getEnd());
00135   if (attr.isA(Forecast::tag_total))
00136     return PythonObject(getTotal());
00137   if (attr.isA(Forecast::tag_consumed))
00138     return PythonObject(getConsumed());
00139   if (attr.isA(Tags::tag_weight))
00140     return PythonObject(getWeight());
00141   return Demand::getattro(attr);
00142 }
00143 
00144 
00145 int ForecastBucket::setattro(const Attribute& attr, const PythonObject& field)
00146 {
00147   if (attr.isA(Forecast::tag_total))
00148     setTotal(field.getDouble());
00149   else if (attr.isA(Forecast::tag_consumed))
00150     setConsumed(field.getDouble());
00151   else if (attr.isA(Tags::tag_weight))
00152     setWeight(field.getDouble());
00153   else
00154     return Demand::setattro(attr, field);
00155   return 0;  // OK
00156 }
00157 
00158 
00159 } // end namespace