/[ascend]/trunk/pygtk/ascpy.i
ViewVC logotype

Contents of /trunk/pygtk/ascpy.i

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1960 - (show annotations) (download)
Mon Nov 17 12:15:56 2008 UTC (15 years, 7 months ago) by jpye
File size: 13779 byte(s)
Add setIntValue to Python wrapper for Instance class.
Added getModule method for Type, planned for use with canvas-based modeller.
1 /* : set syntax=cpp : */
2 /*
3 SWIG interface routines to read a file into the library
4 */
5
6 %module(directors=1) ascpy
7
8 %include <python/std_string.i>
9 %include <python/std_except.i>
10 %include <python/std_vector.i>
11 %include <python/std_map.i>
12 %include <python/std_set.i>
13
14 %{
15 #include "library.h"
16 #include "compiler.h"
17 #include "type.h"
18 #include "instance.h"
19 #include "variable.h"
20 #include "relation.h"
21 #include "name.h"
22 #include "reporter.h"
23 #include "simulation.h"
24 #include "solver.h"
25 #include "symchar.h"
26 #include "set.h"
27 #include "dimensions.h"
28 #include "units.h"
29 #include "extmethod.h"
30 #include "plot.h"
31 #include "curve.h"
32 #include "solverparameters.h"
33 #include "solverstatus.h"
34 #include "solverreporter.h"
35 #include "incidencematrix.h"
36 #include "registry.h"
37 #include "annotation.h"
38 #include "simulation.h"
39
40 extern "C"{
41 #include <compiler/importhandler.h>
42 #include <utilities/ascMalloc.h>
43 }
44
45 #ifdef ASC_WITH_DMALLOC
46 # include <dmalloc.h>
47 #endif
48
49 %}
50
51 // All STL runtime_errors caught to Python
52
53 %exception {
54 try {
55 $action
56 }
57 catch (std::range_error &e) {
58 SWIG_exception(SWIG_IndexError,e.what());
59 }
60 catch (std::runtime_error &e) {
61 SWIG_exception(SWIG_RuntimeError,e.what());
62 }
63 }
64
65 // Import the preferences module
66 %pythoncode {
67 import preferences;
68 }
69
70 // Set-valued instance variable
71 %pythoncode {
72 class SetIter:
73 def __init__(self,set):
74 self.set=set
75 self.index=0
76 def next(self):
77 if self.index==self.set.length():
78 raise StopIteration
79 self.index = self.index + 1
80 return self.set[self.index]
81 }
82
83 template<class T>
84 class ASCXX_Set{
85 private:
86 ASCXX_Set();
87 public:
88 const T at(const unsigned long&) const;
89 const unsigned long length() const;
90 };
91 %extend ASCXX_Set<long>{
92 %pythoncode {
93 def __getitem__(self, index):
94 return self.at(index)
95 def __iter__(self):
96 return SetIter(self)
97 }
98 }
99 %extend ASCXX_Set<SymChar>{
100 %pythoncode {
101 def __getitem__(self, index):
102 return self.at(index)
103 def __iter__(self):
104 return SetIter(self)
105 }
106 }
107
108
109 %template(ModuleVector) std::vector<Module>;
110 %template(TypeVector) std::vector<Type>;
111 %template(MethodVector) std::vector<Method>;
112 %template(InstancVector) std::vector<Instanc>;
113 %template(ExtMethodVector) std::vector<ExtMethod>;
114 %template(SetInt) ASCXX_Set<long>;
115 %template(SetString) ASCXX_Set<SymChar>;
116 %template(DoubleVector) std::vector<double>;
117 %template(IntVector) std::vector<int>;
118 %template(CurveVector) std::vector<Curve>;
119 %template(StringVector) std::vector<std::string>;
120 %template(IntStringMap) std::map<int,std::string>;
121 %template(AnnotationVector) std::vector<Annotation>;
122 %template(UnitsVector) std::vector<UnitsM>;
123 %template(TypeSet) std::set<Type>;
124
125 %rename(Instance) Instanc;
126 %rename(Name) Nam;
127 %rename(getSetIntValue) Instanc::getSetValue<long>;
128 %rename(getSetStringValue) Instanc::getSetValue<SymChar>;
129 %rename(Units) UnitsM;
130
131 // Grab a Python function object as a Python object.
132 %typemap(in) PyObject *pyfunc {
133 if (!PyCallable_Check($input)) {
134 PyErr_SetString(PyExc_TypeError, "Need a callable object!");
135 return NULL;
136 }
137 $1 = $input;
138 }
139
140 //----------------------------
141 // REPORTER: callbacks to python
142 class Reporter{
143 private:
144 ~Reporter();
145 Reporter();
146 public:
147 // use 'getReporter' instead of 'Reporter::Instance()' in python
148 void setErrorCallback(error_reporter_callback_t callback, void *client_data);
149 void setPythonErrorCallback(PyObject *pyfunc);
150 void clearPythonErrorCallback();
151 };
152
153 %extend Reporter {
154 void reportError(const char *msg){
155 ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"%s", msg);
156 }
157 void reportNote(const char *msg){
158 ERROR_REPORTER_NOLINE(ASC_USER_NOTE,"%s",msg);
159 }
160 void reportWarning(const char *msg){
161 ERROR_REPORTER_NOLINE(ASC_USER_WARNING,"%s",msg);
162 }
163 void reportSuccess(const char *msg){
164 ERROR_REPORTER_NOLINE(ASC_USER_SUCCESS,"%s",msg);
165 }
166 }
167
168 // There are problems with Instance(), so use this instead:
169 Reporter *getReporter();
170
171 //----------------------------------------
172 // UNITS AND DIMENSIONS
173
174
175 class UnitsM;
176
177 %include "dimensions.h"
178 %include "units.h"
179
180 %extend UnitsM{
181 %pythoncode{
182 def getConvertedValue(self,si_value):
183 """Return an SI value converted to self's units of measurement."""
184 _v = si_value / self.getConversion()
185 _s = str(_v)
186 _n = self.getName().toString()
187 if _n=="1":
188 return _s
189 elif _n=="?":
190 return _s
191 else:
192 return _s + " " + _n;
193 }
194 }
195
196 /*
197 This function creates default (SI) units for any dimension given. Most
198 of the time you will want to use custom units in place of these, eg
199 'N' instead of 'kg*m/s^2'.
200 */
201
202 %rename(__str__) Dimensions::toString;
203
204 %extend Dimensions{
205 %pythoncode {
206
207 def __str__(self):
208 return self.toString()
209
210 def getDefaultUnits(self):
211 """Return the default (SI) units for a specific set of dimensions."""
212 if self.isWild():
213 return Units("?");
214
215 # create a string representation of the current dimensions
216 numparts=[]
217 denparts=[]
218 for i in range(0, self.MAX_DIMS):
219 baseunit = self.getBaseUnit(i);
220 num = self.getFractionNumerator(i)
221 den = self.getFractionDenominator(i)
222 if num > 0:
223 if den == 1:
224 if num == 1:
225 numparts.append(baseunit)
226 else:
227 numparts.append("%s^%d" % (baseunit, num) )
228 else:
229 numparts.append("%s^(%d/%d)" % (baseunit, num, den) )
230 elif num < 0:
231 if den == 1:
232 if num == -1:
233 denparts.append(baseunit)
234 else:
235 denparts.append("%s^%d" % (baseunit, -num) )
236 else:
237 denparts.append("%s^(%d/%d)" % (baseunit, -num, den) )
238
239 if len(numparts):
240 str = "*".join(numparts)
241 else:
242 str = "1"
243
244 if len(denparts):
245 str = str + "/" + "/".join(denparts)
246
247 return Units(str)
248
249 }
250 }
251
252 /*
253 some python code for nice unicode unit strings, need to extend the units.c code as well though.
254
255 elif num == 2:
256 numparts.append(baseunit + ur'\u00b2')
257 elif num == 3:
258 numparts.append(baseunit + ur'\u00b3')
259
260 str = ur'\u00b7'.join(numparts)
261 */
262 //----------------------------
263
264 %typemap(in) const SymChar& {
265 $1 = new SymChar(PyString_AsString($input));
266 }
267
268 %include "library.h"
269
270 class SymChar{
271 public:
272 SymChar(const std::string &);
273 const char *toString() const;
274 };
275 %extend SymChar{
276 const char *__repr__(){
277 return self->toString();
278 }
279 }
280
281 class Module{
282 public:
283 const char *getName() const;
284 const char *getFilename() const;
285 const struct tm *getMtime() const;
286 };
287
288 %include "method.h"
289
290 %ignore Method::getInternalType;
291 %ignore Method::getSym;
292
293 // Renamed in python as 'Name'
294 class Nam{
295 public:
296 Nam(const SymChar &);
297 const std::string getName() const;
298 };
299
300 %include "compiler.h"
301 /* we can always disown Compiler * as it's a singleton */
302 %apply SWIGTYPE *DISOWN { Compiler * };
303 %apply SWIGTYPE *DISOWN { Simulation * };
304
305 %include "type.h"
306
307 %extend Type{
308 const char *__repr__(){
309 return self->getName().toString();
310 }
311
312 %pythoncode{
313 def getPreferredUnits(self):
314 """Return preferred units for an instance, which is done by lookup per atom type."""
315 if not self.isRefinedReal():
316 return None
317
318 _pref = preferences.Preferences()
319 #print "Checking for preferred units for %s" % self.getName()
320 _u = _pref.getPreferredUnits(self.getName().toString())
321 if _u is None:
322 # no preferred units set
323 return None
324 _units = Units(_u);
325
326 if _units.getDimensions() != self.getDimensions():
327 getReporter().reportWarning("Preferred units '%s' for type '%s' are not dimensionally correct: ignoring." % (_u, self.getName()) );
328 return None
329
330 return _units;
331 }
332 }
333
334 typedef enum{
335 ASCXX_INST_STATUS_UNKNOWN=0, ASCXX_VAR_FIXED, ASCXX_VAR_UNSOLVED, ASCXX_VAR_ACTIVE, ASCXX_VAR_SOLVED
336 , ASCXX_REL_INACTIVE
337 } InstanceStatus;
338
339 /*
340 we really want to get rid of this and just %include...
341 */
342 class Instanc{
343 private:
344 Instanc();
345 public:
346 Instanc(Instance *);
347 Instanc(Instance *, SymChar &name);
348 ~Instanc();
349 std::vector<Instanc> getChildren();
350 const std::string getKindStr() const;
351 const SymChar &getName();
352 const Type getType() const;
353 const bool isAtom() const;
354 const bool isFixed() const;
355 const bool isIncluded() const;
356 const bool isFund() const;
357 const bool isConst() const;
358 const bool isAssigned() const;
359 const bool isCompound() const;
360 const bool isRelation() const;
361 const bool isLogicalRelation() const;
362 const bool isWhen() const;
363 const bool isSet() const; // a set (group) of things
364 const bool isSetInt() const;
365 const bool isSetString() const;
366 const bool isSetEmpty() const;
367 const bool isArray() const;
368 const bool isDefined() const;
369 const bool isBool() const;
370 const bool isInt() const;
371 const bool isSymbol() const;
372 const bool isReal() const;
373 const bool isModel() const;
374
375 const double getRealValue() const;
376 const bool isDimensionless() const;
377 const Dimensions getDimensions() const;
378 const bool getBoolValue() const;
379 const long getIntValue() const;
380 const SymChar getSymbolValue() const;
381 const std::string getValueAsString() const; ///< Use carefully: rounding will occur for doubles!
382
383 const std::string getRelationAsString(const Instanc &relative_to) const;
384 const double getResidual() const;
385 const bool getLogicalResidual() const;
386
387 Plot getPlot() const;
388
389 const bool isPlottable() const;
390 const ASCXX_Set<long> getSetValue<long>() const;
391 const ASCXX_Set<SymChar> getSetValue<SymChar>() const;
392 const bool isChildless() const;
393 void setFixed(const bool &val=true);
394 void setIncluded(const bool &val=true);
395 void setRealValue(const double &val);
396 void setRealValueWithUnits(const double &, const char *);
397 void setBoolValue(const bool &val);
398 void setIntValue(const long &val);
399 void setSymbolValue(const SymChar &sym);
400 void write(FILE *fp);
401
402 const InstanceStatus getStatus() const;
403
404 void setLowerBound(const double &);
405 void setUpperBound(const double &);
406 void setNominal(const double &);
407 const double getLowerBound() const;
408 const double getUpperBound() const;
409 const double getNominal() const;
410
411 const std::vector<Instanc> getClique() const;
412 };
413
414 %extend Instanc{
415 const char *__repr__(){
416 return self->getName().toString();
417 }
418 Instanc __getattr__(const char *name){
419 return self->getChild(SymChar(name));
420 }
421 Instanc __getitem__(const long &index){
422 return self->getChild(index);
423 }
424 double __float__(){
425 if(self->isReal()){
426 return self->getRealValue();
427 }else{
428 throw std::runtime_error("Can't cast this instance to float");
429 }
430 }
431
432 %pythoncode {
433 def getSetValue(self):
434 """Return the value of a set, as a integer or string Python sequence."""
435 if self.isSetInt():
436 return self.getSetIntValue()
437 elif self.isSetString():
438 return self.getSetStringValue()
439 elif self.isSetEmpty():
440 return set()
441 else:
442 raise RuntimeError("getSetValue: unknown set type");
443
444 def getValue(self):
445 """Returns an instance value, including units if applicable."""
446 #print "GETTING VALUE OF %s" % self.getName()
447 if self.isCompound():
448 return ""
449 elif self.isRelation():
450 return self.getResidual()
451 elif self.isWhen():
452 return "WHEN"
453 elif self.isSet():
454 _s = set(self.getSetValue());
455 #for _v in self.getSetValue():
456 # _s.add( _v )
457 return _s
458
459 elif ( self.isAtom() or self.isFund() ) and not self.isDefined():
460 return "undefined"
461 elif self.isReal():
462 return self.getRealValueAndUnits()
463 elif self.isBool():
464 return self.getBoolValue()
465 elif self.isInt():
466 return self.getIntValue()
467 elif self.isSymbol():
468 return self.getSymbolValue()
469 elif self.isLogicalRelation():
470 return self.getLogicalResidual()
471 else:
472 return "UNKNOWN TYPE"
473 #raise RuntimeError("Unknown value model type="+self.getType().getName().toString()+", instance kind=".getKindStr())
474
475 def getRealValueAndUnits(self):
476 """Return real-valued instance value as a string, converted to, and including, its preferred units."""
477 if not self.isReal():
478 raise TypeError
479 if self.isFund():
480 return self.getRealValue();
481 _u = self.getType().getPreferredUnits();
482 if _u is None:
483 _u = self.getDimensions().getDefaultUnits()
484 return _u.getConvertedValue(self.getRealValue())
485
486 def to(self,units):
487 """Returns an instance value converted to specified units."""
488 if not self.isReal():
489 raise TypeError
490 if units.__class__==str:
491 units = Units(units);
492 if units.__class__!=Units:
493 raise TypeError
494 return self.getRealValue() / units.getConversion()
495
496 def setFixedValue(self,val):
497 """Set a value to 'fixed', and specify its value, at the same time."""
498 if not self.isFixed():
499 self.setFixed();
500 # getReporter().reportError("Setting value of %s to %s" % (self.getName().toString(),val))
501 self.setRealValue(val);
502
503 def __coerce__(self,other):
504 if self.isInt():
505 if other.__class__==int:
506 return self.getIntValue(),int(other)
507 elif other.__class__==float:
508 return float(self.getIntValue()),other
509 elif self.isReal():
510 if other.__class__== int:
511 return self.getRealValue(),float(other)
512 elif other.__class__==float:
513 return self.getRealValue(),other
514 return str(self),str(other)
515
516 def __sub__(self,other):
517 a,b = self.__coerce__(other)
518 return a - b
519
520 def __rsub__(self,other):
521 a,b = self.__coerce__(other)
522 return b - a
523
524 def __add__(self,other):
525 a,b = self.__coerce__(other)
526 return a + b
527
528 def __radd__(self,other):
529 a,b = self.__coerce__(other)
530 return b + a
531 }
532 }
533
534 /*
535 This 'registry' thing is a bit of a hack that allows interface pointers to
536 be registered with libascend so that they can be accessed from external
537 script methods
538 */
539 %include "registry.h"
540 %extend Registry{
541 void set(const char *key, PyObject *obj){
542 /* CONSOLE_DEBUG("Registry::set(PyObject *obj=%p)",obj); */
543 self->setPyObject(key,obj);
544 }
545 }
546
547 void shutdown();
548
549 %{
550 void shutdown(){
551 ascshutdown("Shutdown ASCEND...");
552 }
553 %}
554
555 %include "solver.i"
556
557 %include "extmethod.h"
558
559 %include "annotation.h"
560
561 %include "plot.i"
562
563 %ignore Curve::Curve();
564
565 %include "curve.h"

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22