Changeset 5053:70fd9d4eae0a in orange


Ignore:
Timestamp:
08/02/08 15:39:11 (6 years ago)
Author:
janezd <janez.demsar@…>
Branch:
default
Convert:
cff5d51f0e5bc8fce13493d6f336d4c001e5ff67
Message:
  • attribute measures defined in python can now set needs and can define the thresholdFunction
Location:
source/orange
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • source/orange/callback.cpp

    r3730 r5053  
    11/* 
    2     This file is part of Orange. 
    3  
    4     Orange is free software; you can redistribute it and/or modify 
    5     it under the terms of the GNU General Public License as published by 
    6     the Free Software Foundation; either version 2 of the License, or 
    7     (at your option) any later version. 
    8  
    9     Orange is distributed in the hope that it will be useful, 
    10     but WITHOUT ANY WARRANTY; without even the implied warranty of 
    11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    12     GNU General Public License for more details. 
    13  
    14     You should have received a copy of the GNU General Public License 
    15     along with Orange; if not, write to the Free Software 
    16     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
    17  
    18     Authors: Janez Demsar, Blaz Zupan, 1996--2002 
    19     Contact: janez.demsar@fri.uni-lj.si 
    20 */ 
    21  
     2 This file is part of Orange. 
     3 
     4 Orange is free software; you can redistribute it and/or modify 
     5 it under the terms of the GNU General Public License as published by 
     6 the Free Software Foundation; either version 2 of the License, or 
     7 (at your option) any later version. 
     8 
     9 Orange is distributed in the hope that it will be useful, 
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of 
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     12 GNU General Public License for more details. 
     13 
     14 You should have received a copy of the GNU General Public License 
     15 along with Orange; if not, write to the Free Software 
     16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
     17 
     18 Authors: Janez Demsar, Blaz Zupan, 1996--2002 
     19 Contact: janez.demsar@fri.uni-lj.si 
     20 */ 
    2221 
    2322#include "values.hpp" 
     
    3837#include "callback.ppp" 
    3938 
    40  
    4139PyObject *callCallback(PyObject *self, PyObject *args) 
    42 { PyObject *result; 
    43    
    44   if (PyObject_HasAttrString(self, "__callback")) { 
    45     PyObject *callback = PyObject_GetAttrString(self, "__callback"); 
    46     result = PyObject_CallObject(callback, args); 
    47     Py_DECREF(callback); 
    48   } 
    49   else  
    50     result = PyObject_CallObject(self, args); 
    51  
    52   if (!result) 
    53     throw pyexception(); 
    54  
    55   return result; 
    56 } 
    57  
     40{ 
     41    PyObject *result; 
     42 
     43    if (PyObject_HasAttrString(self, "__callback")) { 
     44        PyObject *callback = PyObject_GetAttrString(self, "__callback"); 
     45        result = PyObject_CallObject(callback, args); 
     46        Py_DECREF(callback); 
     47    } 
     48    else 
     49        result = PyObject_CallObject(self, args); 
     50 
     51    if (!result) 
     52        throw pyexception(); 
     53 
     54    return result; 
     55} 
     56 
     57PyObject *callMethod(char const *method, PyObject *self, PyObject *args) 
     58{ 
     59 
     60    if (PyObject_HasAttrString(self, method)) { 
     61        PyObject *callback = PyObject_GetAttrString(self, method); 
     62        PyObject *result = PyObject_CallObject(callback, args); 
     63        Py_DECREF(callback); 
     64 
     65        if (!result) 
     66            throw pyexception(); 
     67 
     68        return result; 
     69    } 
     70 
     71    raiseErrorWho("Python object does not provide method '%s'", method); 
     72} 
    5873 
    5974PyObject *setCallbackFunction(PyObject *self, PyObject *args) 
    60 { PyObject *func; 
    61   if (!PyArg_ParseTuple(args, "O", &func)) { 
    62     PyErr_Format(PyExc_TypeError, "callback function for '%s' expected", self->ob_type->tp_name); 
    63     Py_DECREF(self); 
    64     return PYNULL; 
    65   } 
    66   else if (!PyCallable_Check(func)) { 
    67     PyErr_Format(PyExc_TypeError, "'%s' object is not callable", func->ob_type->tp_name); 
    68     Py_DECREF(self); 
    69     return PYNULL; 
    70   } 
    71  
    72   PyObject_SetAttrString(self, "__callback", func); 
    73   return self; 
    74 } 
    75  
     75{ 
     76    PyObject *func; 
     77    if (!PyArg_ParseTuple(args, "O", &func)) { 
     78        PyErr_Format(PyExc_TypeError, "callback function for '%s' expected", 
     79                self->ob_type->tp_name); 
     80        Py_DECREF(self); 
     81        return PYNULL; 
     82    } 
     83    else if (!PyCallable_Check(func)) { 
     84        PyErr_Format(PyExc_TypeError, "'%s' object is not callable", 
     85                func->ob_type->tp_name); 
     86        Py_DECREF(self); 
     87        return PYNULL; 
     88    } 
     89 
     90    PyObject_SetAttrString(self, "__callback", func); 
     91    return self; 
     92} 
    7693 
    7794PyObject *callbackReduce(PyObject *self, TOrangeType &basetype) 
    7895{ 
    79   if (self->ob_type == (PyTypeObject *)&basetype) { 
    80     PyObject *packed = packOrangeDictionary(self); 
    81     PyObject *callback = PyDict_GetItemString(packed, "__callback"); 
    82     if (!callback) 
    83       PYERROR(PyExc_AttributeError, "cannot pickle an invalid callback object ('__callback' attribute is missing)", NULL); 
    84  
    85     PyDict_DelItemString(packed, "__callback"); 
    86     return Py_BuildValue("O(O)N", self->ob_type, callback, packed); 
    87   } 
    88   else 
    89     return Py_BuildValue("O()N", self->ob_type, packOrangeDictionary(self)); 
    90 } 
    91  
     96    if (self->ob_type == (PyTypeObject *) &basetype) { 
     97        PyObject *packed = packOrangeDictionary(self); 
     98        PyObject *callback = PyDict_GetItemString(packed, "__callback"); 
     99        if (!callback) 
     100            PYERROR( 
     101                    PyExc_AttributeError, 
     102                    "cannot pickle an invalid callback object ('__callback' attribute is missing)", 
     103                    NULL); 
     104 
     105        PyDict_DelItemString(packed, "__callback"); 
     106        return Py_BuildValue("O(O)N", self->ob_type, callback, packed); 
     107    } 
     108    else 
     109        return Py_BuildValue("O()N", self->ob_type, packOrangeDictionary(self)); 
     110} 
    92111 
    93112bool TFilter_Python::operator()(const TExample &ex) 
    94 {  
    95   PyObject *args = Py_BuildValue("(N)", Example_FromExampleCopyRef(ex)); 
    96   PyObject *result = callCallback((PyObject *)myWrapper, args); 
    97   Py_DECREF(args); 
    98  
    99   bool res = bool(PyObject_IsTrue(result)!=0); 
    100   Py_DECREF(result); 
    101   return res; 
     113{ 
     114    PyObject *args = Py_BuildValue("(N)", Example_FromExampleCopyRef(ex)); 
     115    PyObject *result = callCallback((PyObject *)myWrapper, args); 
     116    Py_DECREF(args); 
     117 
     118    bool res = bool(PyObject_IsTrue(result)!=0); 
     119    Py_DECREF(result); 
     120    return res; 
    102121} 
    103122 
    104123PFilter TFilter_Python::deepCopy() const 
    105124{ 
    106   PyObject *result = PyObject_CallMethod((PyObject *)myWrapper,"deepCopy",NULL); 
    107   if (!result)  
    108     raiseError("An exception has been thrown in method deepCopy!"); 
    109   if (!PyOrFilter_Check(result))  
    110     raiseError("deepCopy is expected to return something derived from Filter"); 
    111    
    112   PFilter fil = PyOrange_AsFilter(result); 
    113   Py_DECREF(result); 
    114   return fil; 
    115 } 
    116  
     125    PyObject *result = PyObject_CallMethod((PyObject *) myWrapper, "deepCopy", 
     126            NULL); 
     127    if (!result) 
     128        raiseError("An exception has been thrown in method deepCopy!"); 
     129    if (!PyOrFilter_Check(result)) 
     130        raiseError( 
     131                "deepCopy is expected to return something derived from Filter"); 
     132 
     133    PFilter fil = PyOrange_AsFilter(result); 
     134    Py_DECREF(result); 
     135    return fil; 
     136} 
    117137 
    118138void TTransformValue_Python::transform(TValue &val) 
    119139{ 
    120   PyObject *args = Py_BuildValue("(N)", Value_FromValue(val)); 
    121   PyObject *result = callCallback((PyObject *)myWrapper, args); 
    122   Py_DECREF(args); 
    123  
    124   PVariable var; 
    125   bool succ = convertFromPython(result, val, var); 
    126   Py_DECREF(result); 
    127  
    128   if (!succ) 
    129     raiseError("TransformValue.__call__'s result cannot be converted to a Value"); 
    130 } 
    131  
    132  
    133 TMeasureAttribute_Python::TMeasureAttribute_Python() 
    134 : TMeasureAttribute(TMeasureAttribute::DomainContingency, true, true) 
    135 {} 
    136  
     140    PyObject *args = Py_BuildValue("(N)", Value_FromValue(val)); 
     141    PyObject *result = callCallback((PyObject *) myWrapper, args); 
     142    Py_DECREF(args); 
     143 
     144    PVariable var; 
     145    bool succ = convertFromPython(result, val, var); 
     146    Py_DECREF(result); 
     147 
     148    if (!succ) 
     149        raiseError( 
     150                "TransformValue.__call__'s result cannot be converted to a Value"); 
     151} 
     152 
     153TMeasureAttribute_Python::TMeasureAttribute_Python() : 
     154    TMeasureAttribute(TMeasureAttribute::DomainContingency, true, true) 
     155{ 
     156} 
    137157 
    138158float TMeasureAttribute_Python::callMeasure(PyObject *args) 
    139159{ 
    140   PyObject *res = callCallback((PyObject *)myWrapper, args); 
    141   PyObject *resf = PyNumber_Float(res); 
    142   Py_DECREF(res); 
    143  
    144   if (!resf) 
    145     raiseError("invalid result from __call__"); 
    146  
    147   float mres = (float)PyFloat_AsDouble(resf);   
    148   Py_DECREF(resf); 
    149   return mres; 
    150 } 
    151  
     160    PyObject *res = callCallback((PyObject *) myWrapper, args); 
     161    PyObject *resf = PyNumber_Float(res); 
     162    Py_DECREF(res); 
     163 
     164    if (!resf) 
     165        raiseError("invalid result from __call__"); 
     166 
     167    float mres = (float) PyFloat_AsDouble(resf); 
     168    Py_DECREF(resf); 
     169    return mres; 
     170} 
     171 
     172float TMeasureAttribute_Python::operator ()(PDistribution d) const 
     173{ 
     174    return (const_cast <TMeasureAttribute_Python *>(this))->callMeasure(Py_BuildValue("(N)", WrapOrange(d))); 
     175} 
     176 
     177float TMeasureAttribute_Python::operator ()(const TDiscDistribution &d) const 
     178{ 
     179    PDiscDistribution nd = new TDiscDistribution(d); 
     180    return (const_cast <TMeasureAttribute_Python *>(this))->callMeasure(Py_BuildValue("(N)", WrapOrange(nd))); 
     181} 
     182 
     183float TMeasureAttribute_Python::operator ()(const TContDistribution &d) const 
     184{ 
     185    PContDistribution nd = new TContDistribution(d); 
     186    return (const_cast <TMeasureAttribute_Python *>(this))->callMeasure(Py_BuildValue("(N)", WrapOrange(nd))); 
     187} 
    152188 
    153189float TMeasureAttribute_Python::operator()(PContingency cont, PDistribution classDistribution, PDistribution apriorClass) 
    154 { return callMeasure(Py_BuildValue("(NNN)", WrapOrange(cont), 
    155                                             WrapOrange(classDistribution), 
    156                                             WrapOrange(apriorClass))); } 
    157  
     190{ 
     191    if (needs != Contingency_Class) { 
     192        return TMeasureAttribute::operator()(cont, classDistribution, apriorClass); 
     193    } 
     194 
     195    return callMeasure(Py_BuildValue("(NNN)", 
     196                    WrapOrange(cont), 
     197                    WrapOrange(classDistribution), 
     198                    WrapOrange(apriorClass))); 
     199} 
    158200 
    159201float TMeasureAttribute_Python::operator()(int attrNo, PDomainContingency dcont, PDistribution apriorClass) 
    160 { return callMeasure(Py_BuildValue("(iNN)", attrNo,  
    161                                             WrapOrange(dcont), 
    162                                             WrapOrange(apriorClass))); } 
    163  
    164 float TMeasureAttribute_Python::operator ()(PDistribution d) const 
    165 {  
    166   return (const_cast <TMeasureAttribute_Python *>(this))->callMeasure(Py_BuildValue("(NOO)", WrapOrange(d), Py_None, Py_None)); 
    167 } 
    168  
    169 float TMeasureAttribute_Python::operator ()(const TDiscDistribution &d) const 
    170 {  
    171   PDiscDistribution nd = new TDiscDistribution(d); 
    172   return (const_cast <TMeasureAttribute_Python *>(this))->callMeasure(Py_BuildValue("(NOO)", WrapOrange(nd), Py_None, Py_None)); 
    173 } 
    174  
    175 float TMeasureAttribute_Python::operator ()(const TContDistribution &d) const 
    176 {  
    177   PContDistribution nd = new TContDistribution(d); 
    178   return (const_cast <TMeasureAttribute_Python *>(this))->callMeasure(Py_BuildValue("(NOO)", WrapOrange(nd), Py_None, Py_None)); 
    179 } 
    180  
     202{ 
     203    if (needs != DomainContingency) { 
     204        return TMeasureAttribute::operator()(attrNo, dcont, apriorClass); 
     205    } 
     206 
     207    return callMeasure(Py_BuildValue("(iNN)", attrNo, WrapOrange(dcont), WrapOrange(apriorClass))); 
     208} 
     209 
     210float TMeasureAttribute_Python::operator()(int attrNo, PExampleGenerator gen, PDistribution apriorClass, int weightID) 
     211{ 
     212    if (needs != Generator) { 
     213        return TMeasureAttribute::operator()(attrNo, gen, apriorClass, weightID); 
     214    } 
     215 
     216    return (const_cast <TMeasureAttribute_Python *>(this))->callMeasure(Py_BuildValue("iNNi", attrNo, WrapOrange(gen), WrapOrange(apriorClass), weightID)); 
     217} 
     218 
     219float TMeasureAttribute_Python::operator()(PVariable var, PExampleGenerator gen, PDistribution apriorClass, int weightID) 
     220{ 
     221    if (needs != Generator) { 
     222        return TMeasureAttribute::operator()(var, gen, apriorClass, weightID); 
     223    } 
     224 
     225    return (const_cast <TMeasureAttribute_Python *>(this))->callMeasure(Py_BuildValue("NNNi", WrapOrange(var), WrapOrange(gen), WrapOrange(apriorClass), weightID)); 
     226} 
     227 
     228void TMeasureAttribute_Python::thresholdFunction(TFloatFloatList &res, 
     229        PVariable var, PExampleGenerator gen, PDistribution apriorClass, 
     230        int weightID) 
     231{ 
     232    if (!computesThresholds) { 
     233        TMeasureAttribute::thresholdFunction(res, var, gen, apriorClass, 
     234                weightID); 
     235    } 
     236 
     237    PyObject *args = Py_BuildValue("NNNi", WrapOrange(var), WrapOrange(gen), 
     238            WrapOrange(apriorClass), weightID); 
     239    PyObject *pyres = callMethod("thresholdFunction", (PyObject *) myWrapper, 
     240            args); 
     241    Py_DECREF(args); 
     242 
     243    if (!PyList_Check(pyres)) { 
     244        Py_DECREF(pyres); 
     245        raiseError( 
     246                "method 'thresholdFunction' should return a list of float tuples"); 
     247    } 
     248 
     249    res.clear(); 
     250    const int lsize = PyList_Size(pyres); 
     251    res.reserve(lsize); 
     252    for (int i = 0; i < lsize; i++) { 
     253        PyObject *litem = PyList_GetItem(pyres, i); 
     254        PyObject *n1 = NULL, *n2 = NULL; 
     255        if (!(PyTuple_Check(litem) && (PyTuple_Size(litem) == 2) 
     256                && ((n1 = PyNumber_Float(PyTuple_GET_ITEM(litem, 0))) != NULL) 
     257                && ((n2 = PyNumber_Float(PyTuple_GET_ITEM(litem, 0))) != NULL))) { 
     258            Py_DECREF(pyres); 
     259            Py_XDECREF(n1); 
     260            Py_XDECREF(n2); 
     261            raiseError( 
     262                    "method 'thresholdFunction' should return a list of float tuples"); 
     263        } 
     264        res.push_back(pair<float, float> (PyFloat_AsDouble(n1), 
     265                PyFloat_AsDouble(n2))); 
     266        Py_DECREF(n1); 
     267        Py_DECREF(n2); 
     268    } 
     269    Py_DECREF(pyres); 
     270} 
    181271 
    182272PClassifier TLearner_Python::operator()(PExampleGenerator eg, const int &weight) 
    183 { if (!eg) 
    184     raiseError("invalid example generator"); 
    185  
    186   PyObject *args = Py_BuildValue("(Ni)", WrapOrange(POrange(eg)), weight); 
    187   PyObject *res = callCallback((PyObject *)myWrapper, args); 
    188   Py_DECREF(args); 
    189  
    190   if (!PyOrClassifier_Check(res))  
    191     raiseError("__call__ is expected to return something derived from Classifier"); 
    192  
    193   PClassifier clsf = PyOrange_AsClassifier(res); 
    194   Py_DECREF(res); 
    195   return clsf; 
    196 } 
    197  
     273{ 
     274    if (!eg) { 
     275        raiseError("invalid example generator"); 
     276    } 
     277 
     278    PyObject *args = Py_BuildValue("(Ni)", WrapOrange(POrange(eg)), weight); 
     279    PyObject *res = callCallback((PyObject *)myWrapper, args); 
     280    Py_DECREF(args); 
     281 
     282    if (!PyOrClassifier_Check(res)) { 
     283        raiseError("__call__ is expected to return something derived from Classifier"); 
     284    } 
     285 
     286    PClassifier clsf = PyOrange_AsClassifier(res); 
     287    Py_DECREF(res); 
     288    return clsf; 
     289} 
    198290 
    199291#include "vectortemplates.hpp" 
     
    201293PAttributedFloatList TLogRegFitter_Python::operator()(PExampleGenerator eg, const int &weightID, PAttributedFloatList &beta_se, float &likelihood, int &status, PVariable &attribute) 
    202294{ 
    203   if (!eg) 
    204     raiseError("invalid example generator"); 
    205  
    206   PyObject *args = Py_BuildValue("(Ni)", WrapOrange(POrange(eg)), weightID); 
    207   PyObject *res = callCallback((PyObject *)myWrapper, args); 
    208   Py_DECREF(args); 
    209  
    210   if (!PyTuple_Check(res) || (PyTuple_Size(res)<2) || !PyInt_Check(PyTuple_GET_ITEM(res, 0))) 
    211     raiseError("invalid result from __call__"); 
    212  
    213   status = (int)PyInt_AsLong(PyTuple_GET_ITEM(res, 0)); 
    214   if (status <= TLogRegFitter::Divergence) { 
    215     if (PyTuple_Size(res) != 4) 
    216       raiseError("invalid result from __call__"); 
    217  
    218     PFloatList beta = ListOfUnwrappedMethods<PAttributedFloatList, TAttributedFloatList, float>::P_FromArguments(PyTuple_GET_ITEM(res, 1)); 
    219     beta_se = ListOfUnwrappedMethods<PAttributedFloatList, TAttributedFloatList, float>::P_FromArguments(PyTuple_GET_ITEM(res, 2)); 
    220     Py_DECREF(res); 
    221     if (!beta || !beta_se || !PyNumber_ToFloat(PyTuple_GET_ITEM(res, 3), likelihood)) 
    222       throw pyexception(); 
    223  
    224     attribute = PVariable(); 
    225     return beta; 
    226   } 
    227   else { 
    228     if (PyTuple_Size(res) != 2) 
    229       raiseError("invalid result from __call__"); 
    230  
    231     attribute = PyOrange_AsVariable(PyTuple_GET_ITEM(res, 1)); 
    232     beta_se = PAttributedFloatList(); 
    233     return PAttributedFloatList(); 
    234   } 
    235 } 
    236  
     295    if (!eg) { 
     296        raiseError("invalid example generator"); 
     297    } 
     298 
     299    PyObject *args = Py_BuildValue("(Ni)", WrapOrange(POrange(eg)), weightID); 
     300    PyObject *res = callCallback((PyObject *)myWrapper, args); 
     301    Py_DECREF(args); 
     302 
     303    if (!PyTuple_Check(res) || (PyTuple_Size(res)<2) || !PyInt_Check(PyTuple_GET_ITEM(res, 0))) { 
     304        raiseError("invalid result from __call__"); 
     305    } 
     306 
     307    status = (int)PyInt_AsLong(PyTuple_GET_ITEM(res, 0)); 
     308    if (status <= TLogRegFitter::Divergence) { 
     309        if (PyTuple_Size(res) != 4) { 
     310            raiseError("invalid result from __call__"); 
     311        } 
     312 
     313        PFloatList beta = ListOfUnwrappedMethods<PAttributedFloatList, TAttributedFloatList, float>::P_FromArguments(PyTuple_GET_ITEM(res, 1)); 
     314        beta_se = ListOfUnwrappedMethods<PAttributedFloatList, TAttributedFloatList, float>::P_FromArguments(PyTuple_GET_ITEM(res, 2)); 
     315        Py_DECREF(res); 
     316        if (!beta || !beta_se || !PyNumber_ToFloat(PyTuple_GET_ITEM(res, 3), likelihood)) { 
     317            throw pyexception(); 
     318        } 
     319 
     320        attribute = PVariable(); 
     321        return beta; 
     322    } 
     323    else { 
     324        if (PyTuple_Size(res) != 2) { 
     325            raiseError("invalid result from __call__"); 
     326        } 
     327 
     328        attribute = PyOrange_AsVariable(PyTuple_GET_ITEM(res, 1)); 
     329        beta_se = PAttributedFloatList(); 
     330        return PAttributedFloatList(); 
     331    } 
     332} 
    237333 
    238334TValue TClassifier_Python::operator ()(const TExample &ex) 
    239 {  
    240   PyObject *args = Py_BuildValue("(Ni)", Example_FromExampleCopyRef(ex), 0); 
    241   PyObject *result = callCallback((PyObject *)myWrapper, args); 
    242   Py_DECREF(args); 
    243  
    244   if (result==Py_None) { 
    245     Py_DECREF(result); 
    246     return classVar ? classVar->DK() : TValue(TValue::INTVAR, valueDK); 
    247   } 
    248    
    249   TValue value; 
    250   if (!convertFromPython(result, value, classVar)) { 
    251     Py_DECREF(result); 
    252     raiseError("invalid result from __call__"); 
    253   } 
    254  
    255   Py_DECREF(result); 
    256   return value; 
    257 } 
    258  
     335{ 
     336    PyObject *args = Py_BuildValue("(Ni)", Example_FromExampleCopyRef(ex), 0); 
     337    PyObject *result = callCallback((PyObject *)myWrapper, args); 
     338    Py_DECREF(args); 
     339 
     340    if (result==Py_None) { 
     341        Py_DECREF(result); 
     342        return classVar ? classVar->DK() : TValue(TValue::INTVAR, valueDK); 
     343    } 
     344 
     345    TValue value; 
     346    if (!convertFromPython(result, value, classVar)) { 
     347        Py_DECREF(result); 
     348        raiseError("invalid result from __call__"); 
     349    } 
     350 
     351    Py_DECREF(result); 
     352    return value; 
     353} 
    259354 
    260355PDistribution TClassifier_Python::classDistribution(const TExample &ex) 
    261 {  
    262   PyObject *args = Py_BuildValue("(Ni)", Example_FromExampleCopyRef(ex), 1); 
    263   PyObject *result=callCallback((PyObject *)myWrapper, args); 
    264   Py_DECREF(args); 
    265  
    266   if (result==Py_None) { 
    267     Py_DECREF(result); 
    268     return PDistribution(classVar); 
    269   } 
    270  
    271   if (PyOrDistribution_Check(result)) { 
    272     PDistribution dist = PyOrange_AsDistribution(result); 
    273     Py_DECREF(result); 
    274     return dist; 
    275   } 
    276  
    277   Py_XDECREF(result); 
    278   raiseError("invalid result from __call__"); 
    279   return PDistribution(); 
    280 } 
    281  
    282  
    283 void TClassifier_Python::predictionAndDistribution(const TExample &ex, TValue &val, PDistribution &dist) 
    284 {  
    285   PyObject *args = Py_BuildValue("(Ni)", Example_FromExampleCopyRef(ex), 2); 
    286   PyObject *result=callCallback((PyObject *)myWrapper, args); 
    287   Py_DECREF(args); 
    288  
    289   if (result==Py_None) { 
    290     Py_DECREF(result); 
    291     if (classVar) { 
    292       val = classVar->DK(); 
    293       dist = PDistribution(classVar); 
    294     } 
    295     else { 
    296       val = TValue(TValue::INTVAR, valueDK); 
    297       dist = PDistribution(); 
    298     } 
    299     return; 
    300   } 
    301  
    302   PyObject *obj1; 
    303   if (   !PyArg_ParseTuple(result, "OO&", &obj1, cc_Distribution, &dist) 
    304       || !convertFromPython(obj1, val, classVar)) { 
     356{ 
     357    PyObject *args = Py_BuildValue("(Ni)", Example_FromExampleCopyRef(ex), 1); 
     358    PyObject *result = callCallback((PyObject *) myWrapper, args); 
     359    Py_DECREF(args); 
     360 
     361    if (result == Py_None) { 
     362        Py_DECREF(result); 
     363        return PDistribution(classVar); 
     364    } 
     365 
     366    if (PyOrDistribution_Check(result)) { 
     367        PDistribution dist = PyOrange_AsDistribution(result); 
     368        Py_DECREF(result); 
     369        return dist; 
     370    } 
     371 
    305372    Py_XDECREF(result); 
    306373    raiseError("invalid result from __call__"); 
    307   } 
    308  
    309   Py_DECREF(result); 
    310 } 
    311  
    312  
     374    return PDistribution(); 
     375} 
     376 
     377void TClassifier_Python::predictionAndDistribution(const TExample &ex, 
     378        TValue &val, PDistribution &dist) 
     379{ 
     380    PyObject *args = Py_BuildValue("(Ni)", Example_FromExampleCopyRef(ex), 2); 
     381    PyObject *result = callCallback((PyObject *) myWrapper, args); 
     382    Py_DECREF(args); 
     383 
     384    if (result == Py_None) { 
     385        Py_DECREF(result); 
     386        if (classVar) { 
     387            val = classVar->DK(); 
     388            dist = PDistribution(classVar); 
     389        } 
     390        else { 
     391            val = TValue(TValue::INTVAR, valueDK); 
     392            dist = PDistribution(); 
     393        } 
     394        return; 
     395    } 
     396 
     397    PyObject *obj1; 
     398    if (!PyArg_ParseTuple(result, "OO&", &obj1, cc_Distribution, &dist) 
     399            || !convertFromPython(obj1, val, classVar)) { 
     400        Py_XDECREF(result); 
     401        raiseError("invalid result from __call__"); 
     402    } 
     403 
     404    Py_DECREF(result); 
     405} 
    313406 
    314407PStringList PStringList_FromArguments(PyObject *arg); 
    315408 
    316409PClassifier TTreeSplitConstructor_Python::operator()( 
    317    PStringList &descriptions, PDiscDistribution &subsetSizes, float &quality, int &spentAttribute, 
    318    PExampleGenerator gen, const int &weightID, PDomainContingency dcont, PDistribution apriorClass, const vector<bool> &candidates, PClassifier nodeClassifier) 
    319  
    320 { if (!gen) 
    321     raiseError("invalid example generator"); 
    322    
    323   PyObject *pycandidates = PYNULL; 
    324   if (candidates.size()) { 
    325     pycandidates = PyList_New(candidates.size()); 
    326     int it = 0; 
    327     const_ITERATE(vector<bool>, ci, candidates) 
    328       PyList_SetItem(pycandidates, it++, PyInt_FromLong(*ci ? 1 : 0)); 
    329   } 
    330   else { 
    331     int as = gen->domain->attributes->size(); 
    332     pycandidates = PyList_New(as); 
    333     while (as--) 
    334       PyList_SetItem(pycandidates, as, PyInt_FromLong(1)); 
    335   } 
    336  
    337   PyObject *args = Py_BuildValue("(NiNNNN)", WrapOrange(gen), weightID, WrapOrange(dcont), WrapOrange(apriorClass), pycandidates, WrapOrange(nodeClassifier)); 
    338   PyObject *res = callCallback((PyObject *)myWrapper, args); 
    339   Py_DECREF(args); 
    340  
    341   if (res==Py_None) { 
    342     Py_DECREF(res); 
    343     return PClassifier(); 
    344   } 
    345  
    346   PClassifier classifier; 
    347   PyObject *pydesc = NULL; 
    348   spentAttribute = -1; 
    349   quality = 0.0; 
    350   subsetSizes = PDistribution(); 
    351   if (!PyArg_ParseTuple(res, "O&|OO&fi", ccn_Classifier, &classifier, &pydesc, ccn_DiscDistribution, &subsetSizes, &quality, &spentAttribute)) { 
    352     Py_DECREF(res); 
    353     throw pyexception(); 
    354   } 
    355  
    356   if (classifier && pydesc) 
    357     if (PyOrStringList_Check(pydesc)) 
    358       descriptions = PyOrange_AsStringList(pydesc); 
     410        PStringList &descriptions, PDiscDistribution &subsetSizes, float &quality, int &spentAttribute, 
     411        PExampleGenerator gen, const int &weightID, PDomainContingency dcont, PDistribution apriorClass, const vector<bool> &candidates, PClassifier nodeClassifier) 
     412 
     413{ 
     414    if (!gen) { 
     415        raiseError("invalid example generator"); 
     416    } 
     417 
     418    PyObject *pycandidates = PYNULL; 
     419    if (candidates.size()) { 
     420        pycandidates = PyList_New(candidates.size()); 
     421        int it = 0; 
     422        const_ITERATE(vector<bool>, ci, candidates) 
     423        PyList_SetItem(pycandidates, it++, PyInt_FromLong(*ci ? 1 : 0)); 
     424    } 
    359425    else { 
    360       descriptions = PStringList_FromArguments(pydesc); 
    361       if (!descriptions) { 
     426        int as = gen->domain->attributes->size(); 
     427        pycandidates = PyList_New(as); 
     428        while (as--) 
     429        PyList_SetItem(pycandidates, as, PyInt_FromLong(1)); 
     430    } 
     431 
     432    PyObject *args = Py_BuildValue("(NiNNNN)", WrapOrange(gen), weightID, 
     433            WrapOrange(dcont), WrapOrange(apriorClass), pycandidates, WrapOrange( 
     434                    nodeClassifier)); 
     435    PyObject *res = callCallback((PyObject *) myWrapper, args); 
     436    Py_DECREF(args); 
     437 
     438    if (res==Py_None) { 
     439        Py_DECREF(res); 
     440        return PClassifier(); 
     441    } 
     442 
     443    PClassifier classifier; 
     444    PyObject *pydesc = NULL; 
     445    spentAttribute = -1; 
     446    quality = 0.0; 
     447    subsetSizes = PDistribution(); 
     448    if (!PyArg_ParseTuple(res, "O&|OO&fi", ccn_Classifier, &classifier, &pydesc, ccn_DiscDistribution, &subsetSizes, &quality, &spentAttribute)) { 
    362449        Py_DECREF(res); 
    363450        throw pyexception(); 
    364       } 
    365     } 
    366   else 
    367     descriptions = PStringList(); 
    368  
    369   Py_DECREF(res); 
    370   return classifier; 
    371 } 
    372  
    373  
     451    } 
     452 
     453    if (classifier && pydesc) { 
     454        if (PyOrStringList_Check(pydesc)) { 
     455            descriptions = PyOrange_AsStringList(pydesc); 
     456        } 
     457        else { 
     458            descriptions = PStringList_FromArguments(pydesc); 
     459            if (!descriptions) { 
     460                Py_DECREF(res); 
     461                throw pyexception(); 
     462            } 
     463        } 
     464    } 
     465    else { 
     466        descriptions = PStringList(); 
     467    } 
     468 
     469    Py_DECREF(res); 
     470    return classifier; 
     471} 
    374472 
    375473PExampleGeneratorList PExampleGeneratorList_FromArguments(PyObject *args); 
    376474 
    377475PExampleGeneratorList TTreeExampleSplitter_Python::operator()(PTreeNode node, PExampleGenerator gen, const int &weightID, vector<int> &newWeights) 
    378 { if (!gen) 
    379     raiseError("invalid example generator"); 
    380    
    381   PyObject *args = Py_BuildValue("(NNi)", WrapOrange(node), WrapOrange(gen), weightID); 
    382   PyObject *res = callCallback((PyObject *)myWrapper, args); 
    383   Py_DECREF(args); 
    384  
    385   if (res == Py_None) { 
     476{   if (!gen) { 
     477        raiseError("invalid example generator"); 
     478    } 
     479 
     480    PyObject *args = Py_BuildValue("(NNi)", WrapOrange(node), WrapOrange(gen), weightID); 
     481    PyObject *res = callCallback((PyObject *)myWrapper, args); 
     482    Py_DECREF(args); 
     483 
     484    if (res == Py_None) { 
     485        Py_DECREF(res); 
     486        return PExampleGeneratorList(); 
     487    } 
     488 
     489    PyObject *pygen; 
     490    PyObject *pyweights = NULL; 
     491    if (!PyArg_ParseTuple(res, "O|O", &pygen, &pyweights)) { 
     492        raiseError("invalid result from __call__ (a list of list of examples and, optionally a list of weight ID's expected)"); 
     493    } 
     494 
     495    PExampleGeneratorList eglist = PExampleGeneratorList_FromArguments(pygen); 
     496    if (!eglist) { 
     497        raiseError("invalid result from __call__ (a list of list of examples and, optionally a list of weight ID's expected)"); 
     498    } 
     499 
     500    if (pyweights && (pyweights!=Py_None)) { 
     501        if (!PyList_Check(pyweights) || (PyList_Size(pyweights)!=(int)node->branches->size())) { 
     502            raiseError("invalid result from __call__ (length of weight list should equal the number of branches)"); 
     503        } 
     504        for (int sz = 0, se = PyList_Size(pyweights); sz<se; sz++) { 
     505            PyObject *li = PyList_GetItem(pyweights, sz); 
     506            if (!PyInt_Check(li)) { 
     507                raiseError("invalid weight list (int's expected)."); 
     508            } 
     509            newWeights.push_back(int(PyInt_AsLong(li))); 
     510        } 
     511    } 
     512    else { 
     513        newWeights.clear(); 
     514    } 
     515 
    386516    Py_DECREF(res); 
    387     return PExampleGeneratorList(); 
    388   } 
    389  
    390   PyObject *pygen; 
    391   PyObject *pyweights = NULL; 
    392   if (!PyArg_ParseTuple(res, "O|O", &pygen, &pyweights)) 
    393     raiseError("invalid result from __call__ (a list of list of examples and, optionally a list of weight ID's expected)"); 
    394  
    395   PExampleGeneratorList eglist = PExampleGeneratorList_FromArguments(pygen); 
    396   if (!eglist) 
    397     raiseError("invalid result from __call__ (a list of list of examples and, optionally a list of weight ID's expected)"); 
    398  
    399   if (pyweights && (pyweights!=Py_None)) { 
    400     if (!PyList_Check(pyweights) || (PyList_Size(pyweights)!=(int)node->branches->size())) 
    401       raiseError("invalid result from __call__ (length of weight list should equal the number of branches)"); 
    402        
    403     for (int sz = 0, se = PyList_Size(pyweights); sz<se; sz++) { 
    404       PyObject *li = PyList_GetItem(pyweights, sz); 
    405       if (!PyInt_Check(li)) 
    406         raiseError("invalid weight list (int's expected)."); 
    407       newWeights.push_back(int(PyInt_AsLong(li))); 
    408     }   
    409   } 
    410   else 
    411     newWeights.clear(); 
    412  
    413   Py_DECREF(res); 
    414  
    415   return eglist; 
    416 } 
    417  
    418  
    419  
     517 
     518    return eglist; 
     519} 
    420520 
    421521bool TTreeStopCriteria_Python::operator()(PExampleGenerator gen, const int &weightID, PDomainContingency dcont) 
    422 {  
    423   if (!gen) 
    424     raiseError("invalid example generator"); 
    425  
    426   PyObject *args = Py_BuildValue("(NiN)", WrapOrange(gen), weightID, WrapOrange(dcont)); 
    427   PyObject *result=callCallback((PyObject *)myWrapper, args); 
    428   Py_DECREF(args); 
    429  
    430   bool res = bool(PyObject_IsTrue(result)!=0); 
    431   Py_DECREF(result); 
    432   return res; 
    433 } 
    434  
    435  
     522{ 
     523    if (!gen) { 
     524        raiseError("invalid example generator"); 
     525    } 
     526 
     527    PyObject *args = Py_BuildValue("(NiN)", WrapOrange(gen), weightID, WrapOrange(dcont)); 
     528    PyObject *result=callCallback((PyObject *)myWrapper, args); 
     529    Py_DECREF(args); 
     530 
     531    bool res = bool(PyObject_IsTrue(result)!=0); 
     532    Py_DECREF(result); 
     533    return res; 
     534} 
    436535 
    437536int pt_DiscDistribution(PyObject *args, void *dist); 
    438537 
    439538PTreeNode TTreeDescender_Python::operator()(PTreeNode node, const TExample &ex, PDiscDistribution &distr) 
    440 {  
    441   PyObject *args = Py_BuildValue("(NN)", WrapOrange(node), Example_FromExampleCopyRef(ex)); 
    442   PyObject *result = callCallback((PyObject *)myWrapper, args); 
    443   Py_DECREF(args); 
    444  
    445   if (result == Py_None) { 
    446     Py_DECREF(result); 
    447     distr->clear(); 
    448     return PTreeNode(); 
    449   } 
    450        
    451   PTreeNode newnode; 
    452   distr = PDiscDistribution(); 
    453   if (PyOrTreeNode_Check(result)) 
    454     newnode = PyOrange_AsTreeNode(result); 
    455   else if (!PyArg_ParseTuple(result, "O&|O&", cc_TreeNode, &newnode, pt_DiscDistribution, &distr)) { 
    456     Py_DECREF(result); 
    457     raiseError("invalid result from __call__"); 
    458   } 
    459  
    460   Py_DECREF(result); 
    461   return newnode; 
    462 } 
    463  
     539{ 
     540    PyObject *args = Py_BuildValue("(NN)", WrapOrange(node), Example_FromExampleCopyRef(ex)); 
     541    PyObject *result = callCallback((PyObject *)myWrapper, args); 
     542    Py_DECREF(args); 
     543 
     544    if (result == Py_None) { 
     545        Py_DECREF(result); 
     546        distr->clear(); 
     547        return PTreeNode(); 
     548    } 
     549 
     550    PTreeNode newnode; 
     551    distr = PDiscDistribution(); 
     552    if (PyOrTreeNode_Check(result)) { 
     553        newnode = PyOrange_AsTreeNode(result); 
     554    } 
     555    else if (!PyArg_ParseTuple(result, "O&|O&", cc_TreeNode, &newnode, pt_DiscDistribution, &distr)) { 
     556        Py_DECREF(result); 
     557        raiseError("invalid result from __call__"); 
     558    } 
     559 
     560    Py_DECREF(result); 
     561    return newnode; 
     562} 
    464563 
    465564bool TProgressCallback_Python::operator()(const float &f, POrange o) 
    466 {  
    467   PyObject *args = Py_BuildValue("fN", f, WrapOrange(o)); 
    468   PyObject *result = callCallback((PyObject *)myWrapper, args); 
    469   Py_DECREF(args); 
    470  
    471   bool res = PyObject_IsTrue(result) != 0; 
    472   Py_DECREF(result); 
    473   return res; 
    474 } 
    475  
     565{ 
     566    PyObject *args = Py_BuildValue("fN", f, WrapOrange(o)); 
     567    PyObject *result = callCallback((PyObject *)myWrapper, args); 
     568    Py_DECREF(args); 
     569 
     570    bool res = PyObject_IsTrue(result) != 0; 
     571    Py_DECREF(result); 
     572    return res; 
     573} 
    476574 
    477575PImputer TImputerConstruct_Python::operator()(PExampleGenerator eg, const int &weight) 
    478 {  
    479   if (!eg) 
    480     raiseError("invalid example generator"); 
    481  
    482   PyObject *args = Py_BuildValue("(Ni)", WrapOrange(POrange(eg)), weight); 
    483   PyObject *res = callCallback((PyObject *)myWrapper, args); 
    484   Py_DECREF(args); 
    485  
    486   if (!PyOrImputer_Check(res))  
    487     raiseError("__call__ is expected to return something derived from Imputer"); 
    488  
    489   PImputer imp = PyOrange_AsImputer(res); 
    490   Py_DECREF(res); 
    491   return imp; 
    492 } 
    493  
     576{ 
     577    if (!eg) { 
     578        raiseError("invalid example generator"); 
     579    } 
     580 
     581    PyObject *args = Py_BuildValue("(Ni)", WrapOrange(POrange(eg)), weight); 
     582    PyObject *res = callCallback((PyObject *)myWrapper, args); 
     583    Py_DECREF(args); 
     584 
     585    if (!PyOrImputer_Check(res)) { 
     586        raiseError("__call__ is expected to return something derived from Imputer"); 
     587    } 
     588 
     589    PImputer imp = PyOrange_AsImputer(res); 
     590    Py_DECREF(res); 
     591    return imp; 
     592} 
    494593 
    495594TExample *TImputer_Python::operator()(TExample &example) 
    496595{ 
    497   PyObject *args = Py_BuildValue("(Ni)", Example_FromExampleCopyRef(example), 0); 
    498   PyObject *result = callCallback((PyObject *)myWrapper, args); 
    499   Py_DECREF(args); 
    500  
    501   if (!PyOrExample_Check(result)) 
    502     raiseError("__call__ is expected to return an instance of Example"); 
    503  
    504   TExample *res = CLONE(TExample, PyExample_AS_Example(result)); 
    505   Py_DECREF(result); 
    506   return res; 
     596    PyObject *args = Py_BuildValue("(Ni)", Example_FromExampleCopyRef(example), 0); 
     597    PyObject *result = callCallback((PyObject *)myWrapper, args); 
     598    Py_DECREF(args); 
     599 
     600    if (!PyOrExample_Check(result)) { 
     601        raiseError("__call__ is expected to return an instance of Example"); 
     602    } 
     603 
     604    TExample *res = CLONE(TExample, PyExample_AS_Example(result)); 
     605    Py_DECREF(result); 
     606    return res; 
    507607} 
    508608 
    509609float TRuleEvaluator_Python::operator()(PRule rule, PExampleTable table, const int &weightID, const int &targetClass, PDistribution apriori) 
    510610{ 
    511   if (!table) 
    512     raiseError("invalid example table"); 
    513   if (!rule) 
    514     raiseError("invalid rule"); 
    515   if (!apriori) 
    516     raiseError("invalid prior distribution"); 
    517  
    518   PyObject *args = Py_BuildValue("(NNiiN)", WrapOrange(rule), WrapOrange(table), weightID, targetClass, WrapOrange(apriori)); 
    519   PyObject *result=callCallback((PyObject *)myWrapper, args); 
    520   Py_DECREF(args); 
    521  
    522   if (!PyFloat_Check(result)) 
    523     raiseError("__call__ is expected to return a float value."); 
    524   float res = PyFloat_AsDouble(result); 
    525   Py_DECREF(result); 
    526   return res; 
     611    if (!table) { 
     612        raiseError("invalid example table"); 
     613    } 
     614    if (!rule) { 
     615        raiseError("invalid rule"); 
     616    } 
     617    if (!apriori) { 
     618        raiseError("invalid prior distribution"); 
     619    } 
     620 
     621    PyObject *args = Py_BuildValue("(NNiiN)", WrapOrange(rule), WrapOrange(table), weightID, targetClass, WrapOrange(apriori)); 
     622    PyObject *result=callCallback((PyObject *)myWrapper, args); 
     623    Py_DECREF(args); 
     624 
     625    if (!PyFloat_Check(result)) { 
     626        raiseError("__call__ is expected to return a float value."); 
     627    } 
     628    float res = PyFloat_AsDouble(result); 
     629    Py_DECREF(result); 
     630    return res; 
    527631} 
    528632 
    529633float TChiFunction_Python::operator()(PRule rule, PExampleTable data, const int & weightID, const int & targetClass, PDistribution apriori, float & nonOptimistic_Chi) const 
    530634{ 
    531   if (!data) 
    532     raiseError("invalid example table"); 
    533   if (!rule) 
    534     raiseError("invalid rule"); 
    535   if (!apriori) 
    536     raiseError("invalid prior distribution"); 
    537  
    538   PyObject *args = Py_BuildValue("(NNiiN)", WrapOrange(rule), WrapOrange(data), weightID, targetClass, WrapOrange(apriori)); 
    539   PyObject *result=callCallback((PyObject *)myWrapper, args); 
    540   Py_DECREF(args); 
    541  
    542   float chi; 
    543   if (!PyArg_ParseTuple(result, "ff", &nonOptimistic_Chi, &chi)) 
    544     raiseError("__call__ is expected to return a tuple: (nonOptimistic_Chi, optimistic_chi)"); 
    545   Py_DECREF(result); 
    546   return chi; 
     635    if (!data) { 
     636        raiseError("invalid example table"); 
     637    } 
     638    if (!rule) { 
     639        raiseError("invalid rule"); 
     640    } 
     641    if (!apriori) { 
     642        raiseError("invalid prior distribution"); 
     643    } 
     644 
     645    PyObject *args = Py_BuildValue("(NNiiN)", WrapOrange(rule), WrapOrange(data), weightID, targetClass, WrapOrange(apriori)); 
     646    PyObject *result=callCallback((PyObject *)myWrapper, args); 
     647    Py_DECREF(args); 
     648 
     649    float chi; 
     650    if (!PyArg_ParseTuple(result, "ff", &nonOptimistic_Chi, &chi)) { 
     651        raiseError("__call__ is expected to return a tuple: (nonOptimistic_Chi, optimistic_chi)"); 
     652    } 
     653    Py_DECREF(result); 
     654    return chi; 
    547655} 
    548656 
    549657PEVCDist TEVCDistGetter_Python::operator()(const PRule rule, const int & parentLength, const int & rLength) const 
    550658{ 
    551   if (!rule) 
    552     raiseError("invalid rule"); 
    553  
    554   PyObject *args = Py_BuildValue("(Nii)", WrapOrange(rule), parentLength, rLength); 
    555   PyObject *result=callCallback((PyObject *)myWrapper, args); 
    556   Py_DECREF(args); 
    557  
    558   if (!PyOrEVCDist_Check(result)) 
    559     raiseError("__call__ is expected to return an EVCDist object."); 
    560   PEVCDist res = PyOrange_AsEVCDist(result); 
    561   Py_DECREF(result); 
    562   return res; 
     659    if (!rule) { 
     660        raiseError("invalid rule"); 
     661    } 
     662 
     663    PyObject *args = Py_BuildValue("(Nii)", WrapOrange(rule), parentLength, rLength); 
     664    PyObject *result=callCallback((PyObject *)myWrapper, args); 
     665    Py_DECREF(args); 
     666 
     667    if (!PyOrEVCDist_Check(result)) { 
     668        raiseError("__call__ is expected to return an EVCDist object."); 
     669    } 
     670    PEVCDist res = PyOrange_AsEVCDist(result); 
     671    Py_DECREF(result); 
     672    return res; 
    563673} 
    564674 
    565675bool TRuleValidator_Python::operator()(PRule rule, PExampleTable table, const int &weightID, const int &targetClass, PDistribution apriori) const 
    566676{ 
    567   if (!table) 
    568     raiseError("invalid example table"); 
    569   if (!rule) 
    570     raiseError("invalid rule"); 
    571   if (!apriori) 
    572     raiseError("invalid prior distribution"); 
    573  
    574   PyObject *args = Py_BuildValue("(NNiiN)", WrapOrange(rule), WrapOrange(table), weightID, targetClass, WrapOrange(apriori)); 
    575   PyObject *result=callCallback((PyObject *)myWrapper, args); 
    576   Py_DECREF(args); 
    577  
    578   if (!PyBool_Check(result)) 
    579     raiseError("__call__ is expected to return a Boolean value."); 
    580   bool res = bool(PyObject_IsTrue(result)!=0); 
    581   Py_DECREF(result); 
    582   return res; 
     677    if (!table) { 
     678        raiseError("invalid example table"); 
     679    } 
     680    if (!rule) { 
     681        raiseError("invalid rule"); 
     682    } 
     683    if (!apriori) { 
     684        raiseError("invalid prior distribution"); 
     685    } 
     686 
     687    PyObject *args = Py_BuildValue("(NNiiN)", WrapOrange(rule), WrapOrange(table), weightID, targetClass, WrapOrange(apriori)); 
     688    PyObject *result=callCallback((PyObject *)myWrapper, args); 
     689    Py_DECREF(args); 
     690 
     691    if (!PyBool_Check(result)) { 
     692        raiseError("__call__ is expected to return a Boolean value."); 
     693    } 
     694    bool res = bool(PyObject_IsTrue(result)!=0); 
     695    Py_DECREF(result); 
     696    return res; 
    583697} 
    584698 
    585699PExampleTable TRuleCovererAndRemover_Python::operator()(PRule rule, PExampleTable table, const int &weightID, int &newWeightID, const int &targetClass) const 
    586700{ 
    587   if (!table) 
    588     raiseError("invalid example table"); 
    589   if (!rule) 
    590     raiseError("invalid rule"); 
    591  
    592   PyObject *args = Py_BuildValue("(NNii)", WrapOrange(rule), WrapOrange(table), weightID, targetClass); 
    593   PyObject *result = callCallback((PyObject *)myWrapper, args); 
    594   Py_DECREF(args); 
    595  
    596   PExampleGenerator gen;  
    597   if (!PyArg_ParseTuple(result, "O&O&", pt_ExampleGenerator, &gen, pt_weightByGen(gen), &newWeightID)) 
    598     raiseError("__call__ is expected to return a tuple: (example table, new weight ID)"); 
    599   Py_DECREF(result); 
    600   return gen; 
     701    if (!table) { 
     702        raiseError("invalid example table"); 
     703    } 
     704    if (!rule) { 
     705        raiseError("invalid rule"); 
     706    } 
     707 
     708    PyObject *args = Py_BuildValue("(NNii)", WrapOrange(rule), WrapOrange(table), weightID, targetClass); 
     709    PyObject *result = callCallback((PyObject *)myWrapper, args); 
     710    Py_DECREF(args); 
     711 
     712    PExampleGenerator gen; 
     713    if (!PyArg_ParseTuple(result, "O&O&", pt_ExampleGenerator, &gen, pt_weightByGen(gen), &newWeightID)) { 
     714        raiseError("__call__ is expected to return a tuple: (example table, new weight ID)"); 
     715    } 
     716    Py_DECREF(result); 
     717    return gen; 
    601718} 
    602719 
    603720bool TRuleStoppingCriteria_Python::operator()(PRuleList ruleList, PRule rule, PExampleTable table, const int &weightID) const 
    604721{ 
    605   if (!ruleList) 
    606     raiseError("invalid rule list"); 
    607   if (!table) 
    608     raiseError("invalid example table"); 
    609   if (!rule) 
    610     raiseError("invalid rule"); 
    611  
    612   PyObject *args = Py_BuildValue("(NNNi)", WrapOrange(ruleList), WrapOrange(rule), WrapOrange(table), weightID); 
    613   PyObject *result = callCallback((PyObject *)myWrapper, args); 
    614   Py_DECREF(args); 
    615  
    616   if (!PyBool_Check(result)) 
    617     raiseError("__call__ is expected to return a Boolean value."); 
    618   bool res = bool(PyObject_IsTrue(result)!=0); 
    619   Py_DECREF(result); 
    620   return res; 
     722    if (!ruleList) { 
     723        raiseError("invalid rule list"); 
     724    } 
     725    if (!table) { 
     726        raiseError("invalid example table"); 
     727    } 
     728    if (!rule) { 
     729        raiseError("invalid rule"); 
     730    } 
     731    PyObject *args = Py_BuildValue("(NNNi)", WrapOrange(ruleList), WrapOrange(rule), WrapOrange(table), weightID); 
     732    PyObject *result = callCallback((PyObject *)myWrapper, args); 
     733    Py_DECREF(args); 
     734 
     735    if (!PyBool_Check(result)) { 
     736        raiseError("__call__ is expected to return a Boolean value."); 
     737    } 
     738    bool res = bool(PyObject_IsTrue(result)!=0); 
     739    Py_DECREF(result); 
     740    return res; 
    621741} 
    622742 
    623743bool TRuleDataStoppingCriteria_Python::operator()(PExampleTable table, const int &weightID, const int &targetClass) const 
    624744{ 
    625   if (!table) 
    626     raiseError("invalid example table"); 
    627  
    628   PyObject *args = Py_BuildValue("(Nii)", WrapOrange(table), weightID, targetClass); 
    629   PyObject *result=callCallback((PyObject *)myWrapper, args); 
    630   Py_DECREF(args); 
    631  
    632   if (!PyBool_Check(result)) 
    633     raiseError("__call__ is expected to return a Boolean value."); 
    634   bool res = bool(PyObject_IsTrue(result)!=0); 
    635   Py_DECREF(result); 
    636   return res; 
     745    if (!table) { 
     746        raiseError("invalid example table"); 
     747    } 
     748 
     749    PyObject *args = Py_BuildValue("(Nii)", WrapOrange(table), weightID, targetClass); 
     750    PyObject *result=callCallback((PyObject *)myWrapper, args); 
     751    Py_DECREF(args); 
     752 
     753    if (!PyBool_Check(result)) { 
     754        raiseError("__call__ is expected to return a Boolean value."); 
     755    } 
     756    bool res = bool(PyObject_IsTrue(result)!=0); 
     757    Py_DECREF(result); 
     758    return res; 
    637759} 
    638760 
    639761PRule TRuleFinder_Python::operator ()(PExampleTable table, const int &weightID, const int &targetClass, PRuleList baseRules) 
    640762{ 
    641   if (!table) 
    642     raiseError("invalid example table"); 
    643  
    644   PyObject *args = Py_BuildValue("(NiiN)", WrapOrange(table), weightID, targetClass, WrapOrange(baseRules)); 
    645   PyObject *result = callCallback((PyObject *)myWrapper, args); 
    646   Py_DECREF(args); 
    647  
    648   if (!PyOrRule_Check(result)) 
    649     raiseError("__call__ is expected to return a rule."); 
    650   PRule res = PyOrange_AsRule(result); 
    651   Py_DECREF(result); 
    652   return res; 
     763    if (!table) { 
     764        raiseError("invalid example table"); 
     765    } 
     766 
     767    PyObject *args = Py_BuildValue("(NiiN)", WrapOrange(table), weightID, targetClass, WrapOrange(baseRules)); 
     768    PyObject *result = callCallback((PyObject *)myWrapper, args); 
     769    Py_DECREF(args); 
     770 
     771    if (!PyOrRule_Check(result)) { 
     772        raiseError("__call__ is expected to return a rule."); 
     773    } 
     774    PRule res = PyOrange_AsRule(result); 
     775    Py_DECREF(result); 
     776    return res; 
    653777} 
    654778 
    655779PRuleList TRuleBeamRefiner_Python::operator ()(PRule rule, PExampleTable table, const int &weightID, const int &targetClass) 
    656780{ 
    657   if (!table) 
    658     raiseError("invalid example table"); 
    659   if (!rule) 
    660     raiseError("invalid rule"); 
    661  
    662   PyObject *args = Py_BuildValue("(NNii)", WrapOrange(rule), WrapOrange(table), weightID, targetClass); 
    663   PyObject *result = callCallback((PyObject *)myWrapper, args); 
    664   Py_DECREF(args); 
    665  
    666   if (!PyOrRuleList_Check(result)) 
    667     raiseError("__call__ is expected to return a list of rules."); 
    668   PRuleList res = PyOrange_AsRuleList(result); 
    669   Py_DECREF(result); 
    670   return res; 
     781    if (!table) { 
     782        raiseError("invalid example table"); 
     783    } 
     784    if (!rule) { 
     785        raiseError("invalid rule"); 
     786    } 
     787 
     788    PyObject *args = Py_BuildValue("(NNii)", WrapOrange(rule), WrapOrange(table), weightID, targetClass); 
     789    PyObject *result = callCallback((PyObject *)myWrapper, args); 
     790    Py_DECREF(args); 
     791 
     792    if (!PyOrRuleList_Check(result)) { 
     793        raiseError("__call__ is expected to return a list of rules."); 
     794    } 
     795    PRuleList res = PyOrange_AsRuleList(result); 
     796    Py_DECREF(result); 
     797    return res; 
    671798} 
    672799 
    673800PRuleList TRuleBeamInitializer_Python::operator ()(PExampleTable table, const int &weightID, const int &targetClass, PRuleList baseRules, PRuleEvaluator evaluator, PDistribution prior, PRule &bestRule) 
    674801{ 
    675   if (!table) 
    676     raiseError("invalid example table"); 
    677   if (!evaluator) 
    678     raiseError("invalid evaluator function"); 
    679   if (!prior) 
    680     raiseError("invalid prior distribution"); 
    681  
    682   PyObject *args = Py_BuildValue("(NiiNNNN)", WrapOrange(table), weightID, targetClass, WrapOrange(baseRules), WrapOrange(evaluator), WrapOrange(prior), WrapOrange(bestRule)); 
    683   PyObject *result = callCallback((PyObject *)myWrapper, args); 
    684   Py_DECREF(args); 
    685  
    686   if (!PyOrRuleList_Check(result)) 
    687     raiseError("__call__ is expected to return a list of rules."); 
    688   PRule res = PyOrange_AsRuleList(result); 
    689   Py_DECREF(result); 
    690   return res; 
     802    if (!table) { 
     803        raiseError("invalid example table"); 
     804    } 
     805    if (!evaluator) { 
     806        raiseError("invalid evaluator function"); 
     807    } 
     808    if (!prior) { 
     809        raiseError("invalid prior distribution"); 
     810    } 
     811 
     812    PyObject *args = Py_BuildValue("(NiiNNNN)", WrapOrange(table), weightID, targetClass, WrapOrange(baseRules), WrapOrange(evaluator), WrapOrange(prior), WrapOrange(bestRule)); 
     813    PyObject *result = callCallback((PyObject *)myWrapper, args); 
     814    Py_DECREF(args); 
     815 
     816    if (!PyOrRuleList_Check(result)) { 
     817        raiseError("__call__ is expected to return a list of rules."); 
     818    } 
     819    PRule res = PyOrange_AsRuleList(result); 
     820    Py_DECREF(result); 
     821    return res; 
    691822} 
    692823 
    693824PRuleList TRuleBeamCandidateSelector_Python::operator ()(PRuleList &existingRules, PExampleTable table, const int &weightID) 
    694825{ 
    695   if (!table) 
    696     raiseError("invalid example table"); 
    697   if (!existingRules) 
    698     raiseError("invalid existing rules"); 
    699  
    700   PyObject *args = Py_BuildValue("(NNi)", WrapOrange(existingRules), WrapOrange(table), weightID); 
    701   PyObject *result = callCallback((PyObject *)myWrapper, args); 
    702   Py_DECREF(args); 
    703  
    704   PRuleList candidates;  
    705   if (!PyArg_ParseTuple(result, "O&O&", cc_RuleList, &candidates, cc_RuleList, &existingRules)) 
    706     raiseError("__call__ is expected to return a tuple: (candidate rules, remaining rules)"); 
    707   Py_DECREF(result); 
    708   return candidates; 
     826    if (!table) { 
     827        raiseError("invalid example table"); 
     828    } 
     829    if (!existingRules) { 
     830        raiseError("invalid existing rules"); 
     831    } 
     832 
     833    PyObject *args = Py_BuildValue("(NNi)", WrapOrange(existingRules), WrapOrange(table), weightID); 
     834    PyObject *result = callCallback((PyObject *)myWrapper, args); 
     835    Py_DECREF(args); 
     836 
     837    PRuleList candidates; 
     838    if (!PyArg_ParseTuple(result, "O&O&", cc_RuleList, &candidates, cc_RuleList, &existingRules)) { 
     839        raiseError("__call__ is expected to return a tuple: (candidate rules, remaining rules)"); 
     840    } 
     841    Py_DECREF(result); 
     842    return candidates; 
    709843} 
    710844 
    711845void TRuleBeamFilter_Python::operator ()(PRuleList &rules, PExampleTable table, const int &weightID) 
    712846{ 
    713   if (!table) 
    714     raiseError("invalid example table"); 
    715   if (!rules) 
    716     raiseError("invalid existing rules"); 
    717  
    718   PyObject *args = Py_BuildValue("(NNi)", WrapOrange(rules), WrapOrange(table), weightID); 
    719   PyObject *result = callCallback((PyObject *)myWrapper, args); 
    720   Py_DECREF(args); 
    721  
    722   if (!PyOrRuleList_Check(result)) 
    723     raiseError("__call__ is expected to return a list of rules."); 
    724   rules = PyOrange_AsRuleList(result); 
    725   Py_DECREF(result); 
     847    if (!table) { 
     848        raiseError("invalid example table"); 
     849    } 
     850    if (!rules) { 
     851        raiseError("invalid existing rules"); 
     852    } 
     853 
     854    PyObject *args = Py_BuildValue("(NNi)", WrapOrange(rules), WrapOrange(table), weightID); 
     855    PyObject *result = callCallback((PyObject *)myWrapper, args); 
     856    Py_DECREF(args); 
     857 
     858    if (!PyOrRuleList_Check(result)) { 
     859        raiseError("__call__ is expected to return a list of rules."); 
     860    } 
     861    rules = PyOrange_AsRuleList(result); 
     862    Py_DECREF(result); 
    726863} 
    727864 
    728865PRuleClassifier TRuleClassifierConstructor_Python::operator()(PRuleList rules, PExampleTable table, const int &weightID) 
    729 { if (!rules) 
    730     raiseError("invalid set of rules"); 
    731   if (!table)   
    732     raiseError("invalid example table"); 
    733  
    734   PyObject *args = Py_BuildValue("(NNi)", WrapOrange(rules), WrapOrange(table), weightID); 
    735   PyObject *result = callCallback((PyObject *)myWrapper, args); 
    736   Py_DECREF(args); 
    737  
    738   if (result==Py_None) { 
    739     Py_DECREF(result); 
    740     return PRuleClassifier(); 
    741   } 
    742  
    743   if (!PyOrRuleClassifier_Check(result)) 
    744     raiseError("__call__ is expected to return a rule classifier.");  
    745   PRuleClassifier res = PyOrange_AsRuleClassifier(result); 
    746   Py_DECREF(result);  
    747   return res; 
    748 } 
    749  
    750  
    751 float TKernelFunc_Python::operator ()(const TExample &e1, const TExample &e2){ 
    752     PyObject *args=Py_BuildValue("(NN)", Example_FromExampleCopyRef(e1), Example_FromExampleCopyRef(e2)); 
    753     PyObject *result=callCallback((PyObject *)myWrapper, args); 
    754     Py_DECREF(args); 
    755     float res=PyFloat_AsDouble(result); 
    756     Py_DECREF(result); 
    757     return res; 
    758 } 
    759  
     866{ 
     867    if (!rules) { 
     868        raiseError("invalid set of rules"); 
     869    } 
     870    if (!table) { 
     871        raiseError("invalid example table"); 
     872    } 
     873 
     874    PyObject *args = Py_BuildValue("(NNi)", WrapOrange(rules), WrapOrange(table), weightID); 
     875    PyObject *result = callCallback((PyObject *)myWrapper, args); 
     876    Py_DECREF(args); 
     877 
     878    if (result==Py_None) { 
     879        Py_DECREF(result); 
     880        return PRuleClassifier(); 
     881    } 
     882 
     883    if (!PyOrRuleClassifier_Check(result)) { 
     884        raiseError("__call__ is expected to return a rule classifier."); 
     885    } 
     886    PRuleClassifier res = PyOrange_AsRuleClassifier(result); 
     887    Py_DECREF(result); 
     888    return res; 
     889} 
     890 
     891float TKernelFunc_Python::operator ()(const TExample &e1, const TExample &e2) { 
     892    PyObject *args=Py_BuildValue("(NN)", Example_FromExampleCopyRef(e1), Example_FromExampleCopyRef(e2)); 
     893    PyObject *result=callCallback((PyObject *)myWrapper, args); 
     894    Py_DECREF(args); 
     895    float res=PyFloat_AsDouble(result); 
     896    Py_DECREF(result); 
     897    return res; 
     898} 
    760899 
    761900PExamplesDistance TExamplesDistanceConstructor_Python::operator ()(PExampleGenerator eg, const int &wei, PDomainDistributions dd, PDomainBasicAttrStat das) const 
    762901{ 
    763     PyObject *args=Py_BuildValue("(NiNN)", WrapOrange(eg), wei, WrapOrange(dd), WrapOrange(das)); 
    764     PyObject *result=callCallback((PyObject *)myWrapper, args); 
    765     Py_DECREF(args); 
    766   PExamplesDistance res = PyOrange_AsExamplesDistance(result); 
    767     Py_DECREF(result); 
    768     return res; 
    769 } 
    770  
    771  
     902    PyObject *args=Py_BuildValue("(NiNN)", WrapOrange(eg), wei, WrapOrange(dd), WrapOrange(das)); 
     903    PyObject *result=callCallback((PyObject *)myWrapper, args); 
     904    Py_DECREF(args); 
     905    PExamplesDistance res = PyOrange_AsExamplesDistance(result); 
     906    Py_DECREF(result); 
     907    return res; 
     908} 
    772909 
    773910float TExamplesDistance_Python::operator()(const TExample &e1, const TExample &e2) const 
    774911{ 
    775     PyObject *args=Py_BuildValue("(NN)", Example_FromExampleCopyRef(e1), Example_FromExampleCopyRef(e2)); 
    776     PyObject *result=callCallback((PyObject *)myWrapper, args); 
    777     Py_DECREF(args); 
    778     float res=PyFloat_AsDouble(result); 
    779     Py_DECREF(result); 
    780     return res; 
     912    PyObject *args=Py_BuildValue("(NN)", Example_FromExampleCopyRef(e1), Example_FromExampleCopyRef(e2)); 
     913    PyObject *result=callCallback((PyObject *)myWrapper, args); 
     914    Py_DECREF(args); 
     915    float res=PyFloat_AsDouble(result); 
     916    Py_DECREF(result); 
     917    return res; 
    781918} 
    782919 
    783920/* 
    784 PIM TConstructIM_Python::operator()(PExampleGenerator gen, const vector<bool> &bound, const TVarList &boundSet, const vector<bool> &free, const int &weightID) 
    785 { if (!gen) 
    786     raiseError("invalid example generator"); 
    787  
    788   PyObject *boundList = PyList_New(0); 
    789   PyObject *freeList = PyList_New(0); 
    790   vector<bool>::const_iterator bi(bound.begin()), fi(free.begin()); 
    791  
    792   const_PITERATE(TVarList, vi, gen->domain->attributes) { 
    793     PyObject *m = WrapOrange(*vi); 
    794     if (*(bi++)) 
    795       PyList_Append(boundList, m); 
    796     if (*(fi++)) 
    797       PyList_Append(freeList, m); 
    798     Py_DECREF(m); 
    799   } 
    800  
    801   PyObject *args = Py_BuildValue("(NNNi)", WrapOrange(gen), boundList, freeList, weightID); 
    802   PyObject *res = callCallback((PyObject *)myWrapper, args); 
    803   Py_DECREF(args); 
    804  
    805   if (!PyOrIM_Check(res)) 
    806     raiseError("invalid result from __call__"); 
    807  
    808   PIM im = PyOrange_AsIM(res); 
    809   Py_DECREF(res); 
    810   return im; 
    811 } 
    812 */ 
     921 PIM TConstructIM_Python::operator()(PExampleGenerator gen, const vector<bool> &bound, const TVarList &boundSet, const vector<bool> &free, const int &weightID) 
     922 { if (!gen) 
     923 raiseError("invalid example generator"); 
     924 
     925 PyObject *boundList = PyList_New(0); 
     926 PyObject *freeList = PyList_New(0); 
     927 vector<bool>::const_iterator bi(bound.begin()), fi(free.begin()); 
     928 
     929 const_PITERATE(TVarList, vi, gen->domain->attributes) { 
     930 PyObject *m = WrapOrange(*vi); 
     931 if (*(bi++)) 
     932 PyList_Append(boundList, m); 
     933 if (*(fi++)) 
     934 PyList_Append(freeList, m); 
     935 Py_DECREF(m); 
     936 } 
     937 
     938 PyObject *args = Py_BuildValue("(NNNi)", WrapOrange(gen), boundList, freeList, weightID); 
     939 PyObject *res = callCallback((PyObject *)myWrapper, args); 
     940 Py_DECREF(args); 
     941 
     942 if (!PyOrIM_Check(res)) 
     943 raiseError("invalid result from __call__"); 
     944 
     945 PIM im = PyOrange_AsIM(res); 
     946 Py_DECREF(res); 
     947 return im; 
     948 } 
     949 */ 
  • source/orange/callback.hpp

    r3730 r5053  
    5353  __REGISTER_CLASS 
    5454  TMeasureAttribute_Python(); 
     55  virtual float operator()(int attrNo, PExampleGenerator gen, PDistribution apriorClass, int weightID); 
     56  virtual float operator()(PVariable var, PExampleGenerator, PDistribution apriorClass=PDistribution(), int weightID=0); 
    5557  virtual float operator()(PContingency, PDistribution classDistribution, PDistribution apriorClass=PDistribution()); 
    5658  virtual float operator()(int attrNo, PDomainContingency, PDistribution apriorClass=PDistribution()); 
     
    5961  virtual float operator ()(const TContDistribution &) const; 
    6062 
     63  virtual void thresholdFunction(TFloatFloatList &res, PVariable, PExampleGenerator, PDistribution apriorClass=PDistribution(), int weightID = 0); 
     64 
    6165private: 
    6266  float callMeasure(PyObject *args); 
  • source/orange/measures.hpp

    r4929 r5053  
    7474 
    7575  int needs; //P(&MeasureAttribute_Needs) describes what kind of data is needed for computation 
    76   bool handlesDiscrete; //PR tells whether the measure can handle discrete attributes 
    77   bool handlesContinuous; //PR tells whether the measure can handle continuous attributes 
    78   bool computesThresholds; //PR tells whether the measure can compute threshold functions/maxima for continuous attributes 
     76  bool handlesDiscrete; //P tells whether the measure can handle discrete attributes 
     77  bool handlesContinuous; //P tells whether the measure can handle continuous attributes 
     78  bool computesThresholds; //P tells whether the measure can compute threshold functions/maxima for continuous attributes 
    7979 
    8080  TMeasureAttribute(const int aneeds, const bool handlesDiscrete, const bool handlesContinuous = false, const bool computesThresholds = false); 
     
    106106 
    107107class ORANGE_API TMeasureAttributeFromProbabilities : public TMeasureAttribute { 
    108 public:  
     108public: 
    109109  __REGISTER_ABSTRACT_CLASS 
    110110 
     
    117117 
    118118  virtual float operator()(PContingency, PDistribution classDistribution, PDistribution apriorClass=PDistribution()); 
    119   virtual float operator()(PContingency probabilities, const TDiscDistribution &classProbabilities)=0;  
     119  virtual float operator()(PContingency probabilities, const TDiscDistribution &classProbabilities)=0; 
    120120}; 
    121121 
     
    195195 
    196196    TMeasureAttribute_cost(PCostMatrix costs=PCostMatrix()); 
    197      
     197 
    198198    virtual float operator()(PContingency probabilities, const TDiscDistribution &classProbabilities); 
    199199    float majorityCost(const TDiscDistribution &dval); 
Note: See TracChangeset for help on using the changeset viewer.