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

Contents of /trunk/pygtk/ascpy.i

Parent Directory Parent Directory | Revision Log Revision Log


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

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