50 #include <structmember.h>
53 #include "../utility/simple_logger.hpp"
65 #include "../basecode/header.h"
66 #include "../basecode/global.h"
67 #include "../basecode/Id.h"
68 #include "../basecode/ObjId.h"
69 #include "../utility/utility.h"
70 #include "../shell/Shell.h"
71 #include "../shell/Wildcard.h"
83 "vec.delete() -> None"
85 "\nDelete the underlying moose object. This will invalidate all"
86 "\nreferences to this object and any attempt to access it will raise a"
91 "\n >>>print iaf.path"
96 "setField(fieldname, value_vector) -> None\n"
98 "Set the value of `fieldname` in all elements under this vec.\n"
103 " field to be set.\n"
104 "value: sequence of values\n"
105 " sequence of values corresponding to individual elements"
109 "\n >>> iaf.setField('Vm', 20)"
110 "\n >>> print iaf.Vm"
111 "\n [ 20. 20. 20. 20. 20. 20. 20. 20. 20. 20.]"
112 "\n >>> iaf.setField('Vm', (1, 2, 3, 4, 5, 6, 7, 8, 9, 10))"
113 "\n >>> print iaf.Vm"
114 "\n [ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]"
117 " This is an interface to SetGet::setVec"
130 "Returns integer representation of the id of the element."
134 "Returns the path of this vec object."
138 "Returns the shape of the vec object as a tuple."
142 moose_Id_setField_doc
144 {NULL, NULL, 0, NULL},
177 "An object uniquely identifying a moose array-element.\n"
179 "array-elements are array-like objects which can have one or more"
180 " single-elements within them."
181 " vec can be traversed like a Python sequence and its each item is an"
182 " element identifying single-objects contained in the array element.\n"
184 "you can create multiple references to the same MOOSE object in Python."
185 " As long as they have the same path/id value, they all point to"
186 " the same entity in MOOSE.\n"
188 "Field access are vectorized. For example, if `comp` is a vec of"
189 " Compartments (of size 10), which has a field called `Vm` as membrane voltage, then"
190 " `comp.Vm` returns a"
191 " tuple containing the `Vm` value of all 10 single-elements in this"
192 " vec. There are a few special fields that are unique for vec and are not"
193 " vectorized. These are `path`, `name`, `value`, `shape` and `className`."
194 " There are two ways an vec can be initialized, \n"
195 "(1) create a new array element or \n"
196 "(2) create a reference to an existing object.\n"
200 "\n vec(self, path=path, n=size, g=isGlobal, dtype=className)"
205 "\n path : str/vec/int "
206 "\n Path of an existing array element or for creating a new one. This has"
207 "\n the same format as unix file path: /{element1}/{element2} ... "
208 "\n If there is no object with the specified path, moose attempts to create "
209 "\n a new array element. For that to succeed everything until the last `/`"
210 "\n character must exist or an error is raised"
212 "\n Alternatively, path can be vec or integer value of the Id of an"
213 "\n existing vec object. The new object will be another reference to"
214 "\n the existing object."
216 "\n n : positive int"
217 "\n This is a positive integers specifying the size of the array element"
218 "\n to be created. Thus n=2 will create an vec with 2 elements."
221 "\n Specify if this is a global or local element. Global elements are"
222 "\n shared between nodes in a computing cluster."
225 "\n The vector will be of this moose-class."
230 "\n Path of the vec. In moose vecs are organized in a tree structure"
231 " like unix file system and the paths follow the same convention."
234 "\n Name of the vec."
236 "\n value : int/long"
237 "\n Numeric identifier of the vec. This is unique within a single"
238 " execution. vec comparison is based on this value and its hash is also"
239 " this. So you can compare and sort vecs and use them as dict keys."
241 "\n shape : tuple of ints"
242 "\n Dimensions of the vec (as shape in numpy.ndarray). Currently only"
243 " one-dimensional vecs are implemented."
246 "\n The class of the moose object this vec contains. MOOSE core"
247 " implements its own class system independent of Python. pymoose creates"
248 " thin wrappers around them. This field provides you the moose class"
249 " name as defined in C++"
254 "\n >>> iaf = moose.vec('/iaf', n=10, dtype='IntFire')"
255 "\n >>> iaf.Vm = range(10)"
256 "\n >>> print iaf[5].Vm"
258 "\n >>> print iaf.Vm"
259 "\n array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])"
264 PyVarObject_HEAD_INIT(NULL, 0)
283 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
314 if (attribute ==
"path")
318 else if (attribute ==
"name")
321 return Py_BuildValue(
"s", name.c_str());
323 else if (attribute ==
"value")
327 else if (attribute ==
"shape")
331 else if (attribute ==
"className")
349 return Py_BuildValue(
"s", classname.c_str());
364 size_t pos = trimmed_path.rfind(
"/");
365 if (pos != string::npos)
367 name = trimmed_path.substr(pos+1);
368 parent_path = trimmed_path.substr(0, pos);
376 if (trimmed_path[0] !=
'/')
378 string current_path =
SHELLPTR->getCwe().path();
379 if (current_path !=
"/")
381 parent_path = current_path +
"/" + parent_path;
385 parent_path = current_path + parent_path;
388 else if (parent_path.empty())
392 ObjId parent_id(parent_path);
393 if (parent_id.
bad() )
395 string message =
"Parent element does not exist: ";
396 message += parent_path;
397 PyErr_SetString(PyExc_ValueError, message.c_str());
404 static_cast< NodePolicy >( isGlobal )
406 if (nId ==
Id() && trimmed_path !=
"/" && trimmed_path !=
"/root")
408 string message =
"no such moose class : " + type;
409 PyErr_SetString(PyExc_TypeError, message.c_str());
418 extern PyTypeObject
IdType;
419 PyObject * src = NULL;
421 unsigned int isGlobal = 0;
424 static char _path[] =
"path";
425 static char _dtype[] =
"dtype";
426 static char _size[] =
"n";
427 static char _global[] =
"g";
428 static char * kwlist[] = {_path, _size, _global, _dtype, NULL};
430 char _default_type[] =
"Neutral";
436 unsigned int numData = 0;
444 if (PyArg_ParseTupleAndKeywords(args, kwargs,
"s|IIs:moose_Id_init",
445 kwlist, &path, &numData, &isGlobal,
451 string trimmed_path(path);
453 size_t length = trimmed_path.length();
456 PyErr_SetString(PyExc_ValueError,
457 "moose_Id_init: path must be non-empty string.");
460 self->id_ =
Id(trimmed_path);
463 if (self->id_ !=
Id() || trimmed_path ==
"/" || trimmed_path ==
"/root")
467 PyErr_WarnEx(NULL,
"moose_Id_init_: Length specified does not match that of existing object.", 1);
472 type = _default_type;
477 if (self->id_ ==
Id() && PyErr_Occurred())
486 if (PyArg_ParseTuple(args,
"O:moose_Id_init", &src) &&
Id_SubtypeCheck(src))
488 self->id_ = ((
_Id*)src)->id_;
496 self->id_ = ((
_ObjId*)src)->oid_.id;
501 if (PyArg_ParseTuple(args,
"I:moose_Id_init", &
id))
511 return self->id_.value();
527 cout <<
"Deleting ObjId " << oid << endl;
536 if (self->id_ ==
Id())
538 PyErr_SetString(PyExc_ValueError,
"moose_Id_delete: cannot delete moose shell.");
558 repr <<
"<moose.vec: class="
560 <<
"id=" <<
self->id_.value() <<
", "
561 <<
"path=" <<
self->id_.path() <<
">";
562 return PyString_FromString(repr.str().c_str());
572 return PyString_FromFormat(
"<moose.vec: class=%s, id=%u, path=%s>",
574 self->id_.value(),
self->id_.path().c_str());
580 unsigned int id =
self->id_.value();
581 PyObject * ret = Py_BuildValue(
"I",
id);
594 string path =
self->id_.path();
595 string default_end(
"[0]");
598 path.erase(path.length() - default_end.length(), default_end.length());
600 PyObject * ret = Py_BuildValue(
"s", path.c_str());
613 if (self->id_.element()->hasFields())
619 return (Py_ssize_t)(
self->id_.element()->numData());
629 unsigned int numData = 1;
630 if (self->id_.element()->hasFields())
637 numData =
self->id_.element()->numData();
639 PyObject * ret = PyTuple_New((Py_ssize_t)1);
640 if (PyTuple_SetItem(ret, (Py_ssize_t)0, Py_BuildValue(
"I", numData)))
643 PyErr_SetString(PyExc_RuntimeError,
"moose_Id_getShape: could not set tuple entry.");
661 PyErr_SetString(PyExc_IndexError,
"index out of bounds.");
664 ObjId oid(self->id_.path());
665 if (self->id_.element()->hasFields())
669 oid =
ObjId(self->id_, oid.dataIndex, index);
673 oid =
ObjId(self->id_, index, 0);
682 Py_ssize_t slicelength)
685 PyObject * ret = PyTuple_New(slicelength);
686 bool has_fields =
self->id_.element()->hasFields();
687 for (
int ii = start; ii < end; ii += step)
689 ObjId oid(self->id_.path());
696 PyTuple_SET_ITEM(ret, (Py_ssize_t)(ii-start)/step, value);
717 return moose_Id_fillSlice(
self, start, end, 1, std::max(end - start, (Py_ssize_t) 0));
722 # define SLICE_OBJ(x) (x)
724 # define SLICE_OBJ(x) ((PySliceObject*)(x))
732 if (PySlice_Check(op))
735 Py_ssize_t start, stop, step, slicelength;
737 if (PySlice_GetIndicesEx(
SLICE_OBJ(op), len, &start, &stop, &step, &slicelength) < 0)
743 if (PyInt_Check(op) || PyLong_Check(op))
745 Py_ssize_t
value = PyInt_AsLong(op);
750 PyErr_SetString(PyExc_KeyError,
"moose_Id_subscript: invalid index.");
757 extern PyTypeObject
IdType;
764 else if (!PyObject_IsInstance(other, (PyObject*)&
IdType))
768 else if (op == Py_EQ)
770 ret =
self->id_ == other_id;
772 else if (op == Py_NE)
774 ret =
self->
id_ != other_id;
776 else if (op == Py_LT)
778 ret =
self->
id_ < other_id;
780 else if (op == Py_GT)
782 ret = other_id <
self->
id_;
784 else if (op == Py_LE)
786 ret = (
self->id_ < other_id) || (self->id_ == other_id);
788 else if (op == Py_GE)
790 ret = (other_id <
self->
id_) || (self->id_ == other_id);
805 ret = (((
_ObjId*)obj)->oid_.id ==
self->id_);
817 char * field = PyString_AsString(attr);
828 map<string, string>::const_iterator it =
get_field_alias().find(
string(field));
831 field =
const_cast<char*
>((it->second).c_str());
835 attr = PyString_FromString(field);
841 return PyObject_GenericGetAttr((PyObject*)
self, attr);
846 return PyObject_GenericGetAttr((PyObject*)
self, attr);
853 vector < double > val;
860 vector < string > val;
881 vector < ObjId > val;
895 vector < unsigned int > val;
902 vector < unsigned long > val;
909 vector < float > val;
930 vector < short > val;
937 PyErr_SetString(PyExc_NotImplementedError,
938 "moose_Id_getattro: DataId handling not implemented yet.");
944 msg <<
"moose_Id_getattro: unhandled field type '" << type <<
"'\n"
945 <<
"This is a vec object. Perhaps you are trying to access the field in an"
946 <<
" element in this. Then use indexing to get the element first.";
947 PyErr_SetString(PyExc_ValueError, msg.str().c_str());
964 PyObject * field = NULL;
965 PyObject *
value = NULL;
966 if (!PyArg_ParseTuple(args,
"OO:moose_Id_setField", &field, &value))
983 char * fieldname = NULL;
985 if (PyString_Check(attr))
987 fieldname = PyString_AsString(attr);
991 PyErr_SetString(PyExc_TypeError,
"moose_Id_setattro: Attribute name must be a string");
995 string fieldtype =
getFieldType(moose_class,
string(fieldname));
996 if (fieldtype.length() == 0)
1003 string className = ((PyTypeObject*)PyObject_Type((PyObject*)
self))->tp_name;
1004 if (className !=
"vec")
1007 ret = PyObject_GenericSetAttr((PyObject*)
self, attr, value);
1012 msg <<
"moose_Id_setattro: '" << moose_class <<
"' class has no field '" << fieldname <<
"'" << endl;
1013 PyErr_SetString(PyExc_AttributeError, msg.str().c_str());
1019 if (!PySequence_Check(value))
1023 else if (length != PySequence_Length(value))
1025 PyErr_SetString(PyExc_IndexError,
1026 "moose_Id_setattro: length of the sequence on the right hand side does not match Id size.");
1033 vector<double> _value;
1036 for (
int ii = 0; ii < length; ++ii)
1038 PyObject * vo = PySequence_GetItem(value, ii);
1039 double v = PyFloat_AsDouble(vo);
1041 _value.push_back(v);
1046 double v = PyFloat_AsDouble(value);
1047 _value.assign(length, v);
1054 vector<string> _value;
1057 for (
int ii = 0; ii < length; ++ii)
1059 PyObject * vo = PySequence_GetItem(value, ii);
1060 char * v = PyString_AsString(vo);
1062 _value.push_back(
string(v));
1067 char * v = PyString_AsString(value);
1068 _value.assign(length,
string(v));
1078 for (
int ii = 0; ii < length; ++ii)
1080 PyObject * vo = PySequence_GetItem(value, ii);
1081 int v = PyInt_AsLong(vo);
1083 _value.push_back(v);
1088 int v = PyInt_AsLong(value);
1089 _value.assign(length, v);
1096 vector<unsigned int> _value;
1099 for (
int ii = 0; ii < length; ++ii)
1101 PyObject * vo = PySequence_GetItem(value, ii);
1102 unsigned int v = PyInt_AsUnsignedLongMask(vo);
1104 _value.push_back(v);
1109 unsigned int v = PyInt_AsUnsignedLongMask(value);
1110 _value.assign(length, v);
1117 vector<long> _value;
1120 for (
int ii = 0; ii < length; ++ii)
1122 PyObject * vo = PySequence_GetItem(value, ii);
1123 long v = PyInt_AsLong(vo);
1125 _value.push_back(v);
1130 long v = PyInt_AsLong(value);
1131 _value.assign(length, v);
1138 vector<unsigned long> _value;
1141 for (
int ii = 0; ii < length; ++ii)
1143 PyObject * vo = PySequence_GetItem(value, ii);
1144 unsigned long v = PyInt_AsUnsignedLongMask(vo);
1146 _value.push_back(v);
1151 unsigned long v = PyInt_AsUnsignedLongMask(value);
1152 _value.assign(length, v);
1159 vector<bool> _value;
1162 for (
int ii = 0; ii < length; ++ii)
1164 PyObject * _v = PySequence_GetItem(value, ii);
1165 bool v = (Py_True ==_v) || (PyInt_AsLong(_v) != 0);
1167 _value.push_back(v);
1172 bool v = (Py_True ==
value) || (PyInt_AsLong(value) != 0);
1173 _value.assign(length, v);
1180 vector<char> _value;
1183 for (
int ii = 0; ii < length; ++ii)
1185 PyObject * _v = PySequence_GetItem(value, ii);
1186 char * v = PyString_AsString(_v);
1190 _value.push_back(v[0]);
1195 err <<
"moose_Id_setattro:" << ii <<
"-th element is NUL";
1196 PyErr_SetString(PyExc_ValueError, err.str().c_str());
1203 char * v = PyString_AsString(value);
1206 _value.assign(length, v[0]);
1210 PyErr_SetString(PyExc_ValueError,
"moose_Id_setattro: value is an empty string");
1219 vector<short> _value;
1222 for (
int ii = 0; ii < length; ++ii)
1224 PyObject * vo = PySequence_GetItem(value, ii);
1225 short v = PyInt_AsLong(vo);
1227 _value.push_back(v);
1232 short v = PyInt_AsLong(value);
1233 _value.assign(length, v);
1240 vector<float> _value;
1243 for (
int ii = 0; ii < length; ++ii)
1245 PyObject * vo = PySequence_GetItem(value, ii);
1246 float v = PyFloat_AsDouble(vo);
1248 _value.push_back(v);
1253 float v = PyFloat_AsDouble(value);
1254 _value.assign(length, v);
1265 if (ret && (PyErr_Occurred() == NULL))
Py_ssize_t moose_Id_getLength(_Id *self)
#define ObjId_SubtypeCheck(v)
PyObject * moose_Id_getItem(_Id *self, Py_ssize_t index)
static double op(double x)
bool endswith(const string &full, const string &ending)
PyObject * moose_Id_getattro(_Id *self, PyObject *attr)
PyObject * moose_Id_getSlice(_Id *self, Py_ssize_t start, Py_ssize_t end)
PyObject * moose_Id_getPath(_Id *self)
static PyMappingMethods IdMappingMethods
const map< string, string > & get_field_alias()
int moose_Id_contains(_Id *self, PyObject *obj)
PyObject * moose_Id_delete(_Id *self)
Id create_Id_from_path(string path, unsigned int numData, unsigned int isGlobal, string type)
PyObject * moose_Id_getValue(_Id *self)
#define RAISE_INVALID_ID(ret, msg)
PyObject * moose_Id_getShape(_Id *self)
long moose_Id_hash(_Id *self)
#define Id_SubtypeCheck(v)
PyObject * moose_Id_richCompare(_Id *self, PyObject *other, int op)
PyObject * moose_Id_repr(_Id *self)
static PyMethodDef IdMethods[]
PyObject * to_pytuple(void *obj, char typecode)
PyObject * moose_Id_str(_Id *self)
PyObject * get_Id_attr(_Id *id, string attribute)
PyDoc_STRVAR(moose_Id_delete_doc,"vec.delete() -> None""\n""\nDelete the underlying moose object. This will invalidate all""\nreferences to this object and any attempt to access it will raise a""\nValueError.""\n Example""\n--------""\n >>>iaf.delete()""\n >>>print iaf.path""\n \\ ""\n")
string getFieldType(string className, string fieldName)
static bool setVec(ObjId destId, const string &field, const vector< A > &arg)
static bool isValid(Id id)
int moose_Id_init(_Id *self, PyObject *args, PyObject *kwargs)
PyObject * deleteObjId(ObjId oid)
PyObject * moose_Id_setField(_Id *self, PyObject *args)
PyObject * moose_Id_subscript(_Id *self, PyObject *op)
static A get(const ObjId &dest, const string &field)
std::string trim(const std::string myString, const string &delimiters)
static void getVec(ObjId dest, const string &field, vector< A > &vec)
PyObject * oid_to_element(ObjId oid)
int moose_Id_setattro(_Id *self, PyObject *attr, PyObject *value)
static PyObject * moose_Id_fillSlice(_Id *self, Py_ssize_t start, Py_ssize_t end, Py_ssize_t step, Py_ssize_t slicelength)
static PySequenceMethods IdSequenceMethods