1 """Point and Pointset enhanced array classes.
2
3 (Objects of both classes are mutable.)
4
5 Robert Clewley, February 2006
6 """
7
8
9
10 from __future__ import division
11
12
13 from utils import *
14 from common import *
15 from errors import *
16 from parseUtils import symbolMapClass, mapNames
17
18
19 from numpy import Inf, NaN, isfinite, array2string, r_, c_, \
20 less, greater, linalg, shape, array, argsort, savetxt, \
21 take, zeros, transpose, resize, indices, concatenate, rank
22
23 from numpy import complex, complexfloating, int, integer, \
24 float, floating, float64, complex128, int32
25 from numpy import any, all, alltrue, sometrue, ndarray
26
27
28 import sys
29 from copy import copy, deepcopy
30
31
32 __all__ = ['Point', 'Pointset', 'isparameterized', 'pointsToPointset',
33 'PointInfo', 'makeNonParameterized', 'arrayToPointset',
34 'VarCaller', 'comparePointCoords', 'importPointset',
35 'exportPointset', 'mergePointsets', 'padPointset',
36 'export_pointset_to_CSV']
37
38
39
40
42 """Wrapper for Variable type to call Pointset and return array type."""
43
45 if isinstance(pts, (Point, Pointset)):
46 self.pts = pts
47 else:
48 raise TypeError("Invalid type for pts argument")
49
52
53
54
55
56
57
58 point_keys = ['coorddict', 'coordarray', 'coordtype', 'norm', 'labels']
59
60
62 """N-dimensional point class."""
63
64
65
66
68 if kwd is not None:
69 if kw != {}:
70 raise ValueError("Cannot mix keyword dictionary and keywords")
71 kw = kwd
72 self._parameterized = False
73 self.labels = {}
74 if intersect(kw.keys(), point_keys) == []:
75
76 temp_kw = {}
77 temp_kw['coorddict'] = copy(kw)
78 kw = copy(temp_kw)
79 if 'coorddict' in kw:
80 coorddict = {}
81 try:
82 ct = kw['coordtype']
83 except KeyError:
84 self.coordtype = float
85 else:
86 try:
87 self.coordtype = _num_equivtype[ct]
88 except KeyError:
89 raise TypeError('Coordinate type %s not valid for Point'%str(ct))
90 for c, v in kw['coorddict'].iteritems():
91 if not isinstance(c, str):
92 c_key = repr(c)
93 else:
94 c_key = c
95 if isinstance(v, list):
96 coorddict[c_key] = array(v, self.coordtype)
97 elif isinstance(v, ndarray):
98 if len(v) == 1:
99 coorddict[c_key] = v[0]
100 else:
101 coorddict[c_key] = array(v)
102 assert compareNumTypes(self.coordtype, coorddict[c_key].dtype.type), \
103 'type mismatch'
104 elif isinstance(v, _float_types):
105 assert compareNumTypes(self.coordtype, _float_types), \
106 'type mismatch'
107 coorddict[c_key] = array([v], self.coordtype)
108 elif isinstance(v, _int_types):
109 assert compareNumTypes(self.coordtype, _real_types), \
110 'type mismatch'
111 coorddict[c_key] = array([v], self.coordtype)
112
113
114
115 else:
116 raise TypeError("Must pass numeric type or sequence of "
117 "numeric types")
118 self.coordnames = coorddict.keys()
119
120 self.coordnames.sort()
121 self.dimension = len(self.coordnames)
122 datalist = []
123 for c in self.coordnames:
124 assert not isinstance(coorddict[c], (list, tuple)), 'type mismatch'
125 datalist.append(coorddict[c][0])
126 self.coordarray = array(datalist, self.coordtype)
127 r = rank(self.coordarray)
128 if r == 1:
129 pass
130 elif r == 0:
131 self.coordarray = self.coordarray.ravel()
132 else:
133 raise ValueError("Invalid rank for coordinate array: %i"%r)
134 assert self.dimension == self.coordarray.shape[0], "Invalid coord array"
135 elif 'coordarray' in kw:
136
137
138 if isinstance(kw['coordarray'], ndarray):
139
140
141 array_temp = array(kw['coordarray'])
142 try:
143 self.coordtype = _num_equivtype[array_temp.dtype.type]
144 except KeyError:
145 raise TypeError('Coordinate type %s not valid for Point'%str(ct))
146 elif isinstance(kw['coordarray'], list):
147 try:
148 self.coordtype = _num_equivtype[kw['coordtype']]
149 except KeyError:
150 raise TypeError('Coordinate type %s not valid for Point'%str(ct))
151 array_temp = array(kw['coordarray'], self.coordtype)
152 else:
153 raise TypeError('Coordinate type %s not valid for Point'%str(type(kw['coordarray'])))
154 r = rank(array_temp)
155 if r == 1:
156 self.coordarray = array_temp
157 elif r == 0:
158 self.coordarray = array_temp.ravel()
159 else:
160 raise ValueError("Invalid rank for coordinate array: %i"%r)
161 self.dimension = self.coordarray.shape[0]
162 if 'coordnames' in kw:
163 if isinstance(kw['coordnames'], str):
164 coordnames = [kw['coordnames']]
165 else:
166 coordnames = kw['coordnames']
167 else:
168 coordnames = [str(cix) for cix in range(self.dimension)]
169 if len(coordnames) != self.dimension:
170 print "Point initialization error:"
171 print "Found coord names: ", coordnames, \
172 "(dimension = %s)"%len(coordnames)
173 print "vs. data dimension =", self.dimension
174 raise ValueError("Mismatch between number of coordnames and "
175 "dimension of data")
176 cs = array(coordnames)
177 order = cs.argsort()
178 self.coordnames = cs[order].tolist()
179 self.coordarray = self.coordarray[order]
180 else:
181 raise ValueError("Missing coord info in keywords")
182 assert isUniqueSeq(self.coordnames), 'Coordinate names must be unique'
183 self.makeIxMaps()
184 if 'norm' in kw:
185 if kw['norm'] == 0:
186 raise ValueError("Norm order for point cannot be zero")
187 self._normord = kw['norm']
188 else:
189 self._normord = 2
190
191 if 'labels' in kw:
192 self.addlabel(kw['labels'])
193
194
196 """Map coordinate names and label(s), using a symbol
197 map of class symbolMapClass."""
198 new_coordnames = array(themap(self.coordnames))
199 assert isUniqueSeq(new_coordnames.tolist()), 'Coordinate names must be unique'
200 order = argsort(new_coordnames)
201 self.coordarray = self.coordarray[order]
202 self.coordnames = new_coordnames[order].tolist()
203 self.makeIxMaps()
204
205
206
207
208 self.labels = mapNames(themap, self.labels)
209
210
212 if label is None:
213 pass
214 elif isinstance(label, str):
215 self.labels = {label: {}}
216 elif isinstance(label, tuple) and len(label)==2:
217 if isinstance(label[0], str) and isinstance(label[1], dict):
218 self.labels[label[0]] = label[1]
219 elif isinstance(label, dict):
220 self.labels = label
221 else:
222 raise TypeError("Point label must be a string, a pair, or a dict")
223
224
227
228
230 self._name_ix_map = dict(zip(self.coordnames, range(self.dimension)))
231 self._ix_name_map = copy(self.coordnames)
232
233
234 - def todict(self, aslist=False):
235 """Convert Point to a dictionary of array values (or of list with aslist=True)."""
236 if aslist:
237 return dict(zip(self._ix_name_map, self.coordarray.tolist()))
238 else:
239 return dict(zip(self._ix_name_map, self.coordarray))
240
242 return coord in self.coordnames
243
245 raise NotImplementedError
246
247 - def get(self, coord, d=None):
248 if coord in self.coordnames:
249 return self.__call__(coord)
250 else:
251 return d
252
256
258 return zip(self._ix_name_map, self.coordarray)
259
261 return iter(zip(self._ix_name_map, self.coordarray))
262
264 return self.coordarray.tolist()
265
267 return iter(self.coordarray.tolist())
268
270 return self._ix_name_map
271
273 return iter(self._ix_name_map)
274
276 return k in self.coordnames
277
278
280 try:
281 try:
282
283 return self._name_ix_map[namelist]
284 except TypeError:
285
286 return [self._name_ix_map[n] for n in namelist]
287 except KeyError, e:
288 raise PyDSTool_KeyError("Name not found: "+str(e))
289
290
292 return self.dimension
293
294
296 if x is None:
297 return range(self.dimension)
298 elif x in xrange(self.dimension):
299
300 return [x]
301 elif x in self.coordnames:
302
303 return [self._name_ix_map[x]]
304 elif isinstance(x, _seq_types):
305 if len(x) == 0:
306 return range(self.dimension)
307 else:
308 return [self._force_coords_to_ixlist(el)[0] for el in x]
309 elif isinstance(x, slice):
310 stop = x.stop or self.dimension
311 s1, s2, s3 = x.indices(stop)
312 if s1 < 0 or s2 > self.dimension or s1 >= self.dimension:
313 raise ValueError("Slice index out of range")
314 return range(s1, s2, s3)
315 else:
316 raise ValueError("Invalid coordinate / index: %s"%str(x) + \
317 " -- coord names are: %s"%str(self.coordnames))
318
319
321 if coords in xrange(self.dimension+1):
322 if coords == self.dimension:
323
324
325
326 raise StopIteration
327 else:
328 return self.coordarray[coords]
329 elif coords in self.coordnames:
330 ix = self._name_ix_map[coords]
331 return self.coordarray[ix]
332 else:
333 ixlist = self._force_coords_to_ixlist(coords)
334 return Point({'coordarray': self.coordarray[ixlist],
335 'coordnames': [self.coordnames[i] for i in ixlist],
336 'coordtype': self.coordtype,
337 'norm': self._normord,
338 'labels': self.labels})
339
340 __getitem__ = __call__
341
342
343
344
345
347 """Change coordinate array values."""
348 ixs = self._force_coords_to_ixlist(ixarg)
349 if len(ixs) == 1:
350 val = [val]
351 try:
352 for i, v in zip(ixs,val):
353 self.coordarray[i] = v
354 except TypeError:
355 raise TypeError("Bad value type for Point")
356
357
359 if self.dimension == 1:
360 return self.coordarray[0]
361 else:
362 return self.coordarray
363
364
366 res = self.copy()
367 try:
368 res.coordarray += other.coordarray
369 except AttributeError:
370 res.coordarray += other
371 return res
372
373 __radd__ = __add__
374
376 res = self.copy()
377 try:
378 res.coordarray -= other.coordarray
379 except AttributeError:
380 res.coordarray -= other
381 return res
382
384 res = self.copy()
385 try:
386 res.coordarray = other.coordarray - res.coordarray
387 except AttributeError:
388 res.coordarray = other - res.coordarray
389 return res
390
392 res = self.copy()
393 try:
394 res.coordarray *= other.coordarray
395 except AttributeError:
396 res.coordarray *= other
397 return res
398
399 __rmul__ = __mul__
400
402 res = self.copy()
403 try:
404 res.coordarray /= other.coordarray
405 except AttributeError:
406 res.coordarray /= other
407 return res
408
409 __truediv__ = __div__
410
412 res = self.copy()
413 try:
414 res.coordarray = other.coordarray / res.coordarray
415 except AttributeError:
416 res.coordarray = other / res.coordarray
417 return res
418
419 __rtruediv__ = __rdiv__
420
422 res = self.copy()
423 res.coordarray **= other
424 return res
425
427 res = self.copy()
428 res.coordarray = - res.coordarray
429 return res
430
433
435 try:
436 assert shape(self) == shape(other)
437 if hasattr(other, 'coordnames'):
438 if self.coordnames != other.coordnames:
439 raise ValueError("Coordinate mismatch")
440 return linalg.norm(self.coordarray, self._normord) < \
441 linalg.norm(other.coordarray, self._normord)
442 except (AttributeError, TypeError, AssertionError):
443 return self.coordarray < other
444 except ZeroDivisionError:
445 raise ValueError("Norm order for point cannot be zero")
446
448 try:
449 assert shape(self) == shape(other)
450 if hasattr(other, 'coordnames'):
451 if self.coordnames != other.coordnames:
452 raise ValueError("Coordinate mismatch")
453 return linalg.norm(self.coordarray, self._normord) > \
454 linalg.norm(other.coordarray, self._normord)
455 except (AttributeError, TypeError, AssertionError):
456 return self.coordarray > other
457 except ZeroDivisionError:
458 raise ValueError("Norm order for point cannot be zero")
459
461 try:
462 assert shape(self) == shape(other)
463 if hasattr(other, 'coordnames'):
464 if self.coordnames != other.coordnames:
465 raise ValueError("Coordinate mismatch")
466 return linalg.norm(self.coordarray, self._normord) <= \
467 linalg.norm(other.coordarray, self._normord)
468 except (AttributeError, TypeError, AssertionError):
469 return self.coordarray <= other
470 except ZeroDivisionError:
471 raise ValueError("Norm order for point cannot be zero")
472
474 try:
475 assert shape(self) == shape(other)
476 if hasattr(other, 'coordnames'):
477 if self.coordnames != other.coordnames:
478 raise ValueError("Coordinate mismatch")
479 return linalg.norm(self.coordarray, self._normord) >= \
480 linalg.norm(other.coordarray, self._normord)
481 except (AttributeError, TypeError, AssertionError):
482 return self.coordarray >= other
483 except ZeroDivisionError:
484 raise ValueError("Norm order for point cannot be zero")
485
487 try:
488 assert shape(self) == shape(other)
489 if hasattr(other, 'coordnames'):
490 if self.coordnames != other.coordnames:
491 raise ValueError("Coordinate mismatch")
492 return linalg.norm(self.coordarray, self._normord) == \
493 linalg.norm(other.coordarray, self._normord)
494 except (AttributeError, TypeError, AssertionError):
495 return self.coordarray == other
496 except ZeroDivisionError:
497 raise ValueError("Norm order for point cannot be zero")
498
500 try:
501 assert shape(self) == shape(other)
502 if hasattr(other, 'coordnames'):
503 if self.coordnames != other.coordnames:
504 raise ValueError("Coordinate mismatch")
505 return linalg.norm(self.coordarray, self._normord) != \
506 linalg.norm(other.coordarray, self._normord)
507 except (AttributeError, TypeError, AssertionError):
508 return self.coordarray != other
509 except ZeroDivisionError:
510 raise ValueError("Norm order for point cannot be zero")
511
512
514 precision = 8
515 if verbose == 0:
516 outputStr = "Point with coords:\n"
517 for c in self.coordnames:
518 outputStr += c
519 if c != self.coordnames[-1]:
520 outputStr += "\n"
521 elif verbose > 0:
522 outputStr = ''
523 for c in self.coordnames:
524 v = self.coordarray[self._map_names_to_ixs(c)]
525 if isinstance(v, ndarray):
526 dvstr = str(v[0])
527 else:
528
529 dvstr = str(v)
530 outputStr += c+': '+dvstr
531 if c != self.coordnames[-1]:
532 outputStr += "\n"
533 for label, infodict in self.labels.iteritems():
534 outputStr += "\nLabels: %s (%s)"%(label, str(infodict))
535 return outputStr
536
537
540
541
542 __str__ = __repr__
543
544
545 - def info(self, verboselevel=1):
547
548
550 return linalg.norm(self.coordarray, self._normord)
551
552
554 return Point({'coordarray': copy(self.coordarray),
555 'coordnames': copy(self.coordnames),
556 'coordtype': self.coordtype,
557 'norm': self._normord,
558 'labels': self.labels})
559
560 copy = __copy__
561
562
564 d = copy(self.__dict__)
565
566 d['coordtype'] = _num_type2name[self.coordtype]
567 return d
568
569
574
575
576
577
578
580 """1D parameterized or non-parameterized set of discrete points.
581 (If present, the independent variable must be a float64 or an int32)"""
582
584 if kwd is not None:
585 if kw != {}:
586 raise ValueError("Cannot mix keyword dictionary and keywords")
587 kw = kwd
588 if intersect(kw.keys(), point_keys) == []:
589
590 temp_kw = {}
591 temp_kw['coorddict'] = copy(kw)
592 kw = copy(temp_kw)
593
594 if 'indepvardict' in kw:
595 assert len(kw['indepvardict']) == 1
596 try:
597 it = kw['indepvartype']
598 except KeyError:
599 self.indepvartype = float64
600 else:
601 try:
602 self.indepvartype = _num_equivtype[it]
603 except KeyError:
604 raise TypeError('Independent variable type %s not valid'%str(it))
605 vals = kw['indepvardict'].values()[0]
606 self.indepvarname = kw['indepvardict'].keys()[0]
607 if isinstance(vals, _seq_types):
608 self.indepvararray = array(vals, self.indepvartype)
609 else:
610 try:
611 assert self.indepvartype == _num_equivtype[type(vals)]
612 except (AssertionError, KeyError):
613 raise TypeError("Invalid type for independent variable value")
614 else:
615 self.indepvararray = array([vals], self.indepvartype)
616 elif 'indepvararray' in kw:
617 if 'indepvarname' in kw:
618 self.indepvarname = kw['indepvarname']
619 else:
620 self.indepvarname = 't'
621 vals = kw['indepvararray']
622 if isinstance(vals, list):
623 try:
624 it = kw['indepvartype']
625 except:
626 self.indepvartype = float64
627 else:
628 try:
629 self.indepvartype = _num_equivtype[it]
630 except KeyError:
631 raise TypeError('Independent variable type %s not valid'%str(it))
632 self.indepvararray = array(vals, self.indepvartype)
633 elif isinstance(vals, ndarray):
634
635
636 if rank(vals) in [0,2]:
637 self.indepvararray = array(vals.ravel())
638 else:
639 self.indepvararray = array(vals)
640 try:
641 self.indepvartype = _num_equivtype[self.indepvararray.dtype.type]
642 except KeyError:
643 raise TypeError('Independent variable type '
644 '%s not valid'%self.indepvararray.dtype)
645 else:
646 raise TypeError("Invalid type for independent variable "
647 "array: "+str(type(vals)))
648
649 else:
650
651 self.indepvarname = None
652 self.indepvartype = None
653 self.indepvararray = None
654 self._parameterized = False
655 if self.indepvarname:
656
657 assert isinstance(self.indepvarname, str), \
658 'independent variable name must be a string'
659 try:
660 self.indepvartype = _num_equivtype[self.indepvararray.dtype.type]
661 except KeyError:
662 raise TypeError('Independent variable type '
663 '%s not valid'%self.indepvararray.dtype)
664 r=rank(self.indepvararray)
665 if r == 1:
666 pass
667 elif r == 0:
668 self.indepvararray = self.indepvararray.ravel()
669 else:
670 raise ValueError("Invalid rank for "
671 "independent variable array %i"%r)
672
673
674
675 do_reverse = not isincreasing(self.indepvararray)
676 self._parameterized = True
677
678 if 'coorddict' in kw:
679 coorddict = {}
680 try:
681 ct = kw['coordtype']
682 except KeyError:
683 self.coordtype = float64
684 else:
685 try:
686 self.coordtype = _num_equivtype[ct]
687 except KeyError:
688 raise TypeError('Coordinate type %s not valid for Point'%str(ct))
689 for c, v in kw['coorddict'].iteritems():
690 if isinstance(c, str):
691 c_key = c
692 else:
693 c_key = repr(c)
694 if isinstance(v, list):
695 coorddict[c_key] = array(v, self.coordtype)
696 elif isinstance(v, ndarray):
697
698
699 coorddict[c_key] = array(v, self.coordtype)
700 elif isinstance(v, Pointset):
701 coorddict[c_key] = v.toarray()
702 else:
703 try:
704 assert self.coordtype == _num_equivtype[type(v)]
705 except (AssertionError, KeyError):
706 raise TypeError("Must pass arrays, lists, or numeric types")
707 else:
708 coorddict[c_key] = array([v], self.coordtype)
709 self.coordnames = coorddict.keys()
710
711 self.coordnames.sort()
712 self.dimension = len(self.coordnames)
713 datalist = []
714
715 if self._parameterized:
716 my_len = len(self.indepvararray)
717 else:
718 my_len = len(coorddict[self.coordnames[0]])
719 for c in self.coordnames:
720 xs = coorddict[c]
721 if my_len != len(xs):
722 if self._parameterized:
723 raise ValueError('Independent variable array length must match '
724 'that of each coordinate array')
725 else:
726 raise ValueError('All coordinate arrays must have same length')
727 datalist.append(xs)
728 self.coordarray = array(datalist, self.coordtype)
729 r = rank(self.coordarray)
730 if r == 2:
731 pass
732 elif r == 1:
733 self.coordarray = array([self.coordarray], self.coordtype)
734 elif r == 0:
735 self.coordarray = array([self.coordarray.ravel()], self.coordtype)
736 else:
737 raise ValueError("Invalid rank for coordinate array: %i"%r)
738 assert self.dimension == self.coordarray.shape[0], "Invalid coord array"
739 elif 'coordarray' in kw:
740 if not isinstance(kw['coordarray'], _seq_types):
741 raise TypeError('Coordinate type %s not valid for Pointset'%str(type(kw['coordarray'])))
742 try:
743 ct = kw['coordtype']
744 except KeyError:
745 self.coordtype = float64
746 else:
747 try:
748 self.coordtype = _num_equivtype[ct]
749 except KeyError:
750 raise TypeError('Coordinate type %s not valid'%str(ct))
751
752
753 array_temp = array(kw['coordarray'], self.coordtype)
754 r = rank(array_temp)
755 if r == 2:
756 self.coordarray = array_temp
757 elif r == 1:
758 self.coordarray = array([kw['coordarray']], self.coordtype)
759 elif r == 0:
760 self.coordarray = array([array_temp.ravel()], self.coordtype)
761 else:
762 raise ValueError("Invalid rank for coordinate array %i"%r)
763 self.dimension = self.coordarray.shape[0]
764 if 'coordnames' in kw:
765 if isinstance(kw['coordnames'], str):
766 coordnames = [kw['coordnames']]
767 else:
768 coordnames = kw['coordnames']
769 else:
770 coordnames = [str(cix) for cix in range(self.dimension)]
771 if len(coordnames) != self.dimension:
772 print "Pointset initialization error:"
773 print "Found Coordnames: ", coordnames, \
774 "(dimension = %s)"%len(coordnames)
775 print "vs. data dimension =", self.dimension
776 raise ValueError("Mismatch between number of coordnames and "
777 "dimension of data")
778 cs = array(coordnames)
779 order = cs.argsort()
780 self.coordnames = cs[order].tolist()
781 self.coordarray = take(self.coordarray,order,axis=0)
782 self.coordtype = self.coordarray.dtype.type
783 else:
784 raise ValueError("Missing coord info in keywords")
785 assert isUniqueSeq(self.coordnames), 'Coordinate names must be unique'
786 self.makeIxMaps()
787 if self._parameterized:
788 assert self.indepvarname not in self.coordnames, \
789 "Independent variable name appeared in coordinate names"
790
791 assert self.coordarray.shape[1] == len(self.indepvararray), \
792 ("Coord array length mismatch with independent variable"
793 " array length")
794
795
796
797 if 'checklevel' in kw:
798 checklevel = kw['checklevel']
799 if checklevel in [0,1]:
800 self.checklevel = checklevel
801 else:
802 raise ValueError("Invalid check level")
803 else:
804
805 self.checklevel = 1
806 if 'tolerance' in kw:
807 tol = kw['tolerance']
808 if tol > 0:
809 self._abseps = tol
810 else:
811 raise ValueError("Tolerance must be a positive real number")
812 else:
813 self._abseps = 1e-13
814 if 'name' in kw:
815 if isinstance(kw['name'], str):
816 self.name = kw['name']
817 else:
818 raise TypeError("name argument must be a string")
819 else:
820 self.name = ""
821 if 'norm' in kw:
822 if kw['norm'] == 0:
823 raise ValueError("Norm order for point cannot be zero")
824 self._normord = kw['norm']
825 else:
826 self._normord = 2
827 if 'labels' in kw:
828 try:
829 self.labels = PointInfo(kw['labels'].by_index)
830 except AttributeError:
831 self.labels = PointInfo(kw['labels'])
832 else:
833 self.labels = PointInfo()
834 if 'tags' in kw:
835 self.tags = kw['tags']
836 else:
837 self.tags = {}
838 if self._parameterized:
839 if do_reverse:
840
841
842 self.indepvararray = self.indepvararray[::-1]
843 self.reverse()
844 if not isincreasing(self.indepvararray):
845 raise ValueError("Independent variable values must be in "
846 "increasing order")
847
848
850 """Remove point by index or by coordinate."""
851 if k in self.coordnames:
852 cs = remain(self.coordnames, k)
853 p_result = copy(self[cs])
854 self.coordnames = cs
855 self.coordarray = p_result.coordarray
856 self.labels = p_result.labels
857 self.indepvararray = p_result.indepvararray
858 self.makeIxMaps()
859 else:
860
861 self.remove(k)
862
863
865 """Remove individual Point by its index."""
866 if ix == 0:
867 try:
868 p_result = copy(self[1:])
869 except ValueError:
870
871 raise ValueError("Cannot remove only point in pointset!")
872 else:
873 ix = ix % len(self)
874 p_result = copy(self[:ix])
875 try:
876 p_result.append(self[ix+1:])
877 except ValueError:
878
879 pass
880 self.coordarray = p_result.coordarray
881 self.labels = p_result.labels
882 self.indepvararray = p_result.indepvararray
883 self.makeIxMaps()
884
885
887 """Reverse order of points *IN PLACE*."""
888 self.coordarray = self.coordarray[:,::-1]
889 self.labels.mapIndices(dict(zip(range(0,len(self)),range(len(self)-1,-1,-1))))
890
891 - def rename(self, coord, newcoord):
892 """Rename a coordinate."""
893 try:
894 ix = self.coordnames.index(coord)
895 except ValueError:
896 raise ValueError("No such coordinate: %s"%coord)
897 self.coordnames[ix] = newcoord
898 self.makeIxMaps()
899
901 self._name_ix_map = dict(zip(self.coordnames, range(self.dimension)))
902 self._ix_name_map = copy(self.coordnames)
903 if self._parameterized:
904 self._indepvar_ix_map = makeArrayIxMap(self.indepvararray)
905 else:
906 self._indepvar_ix_map = None
907
908
909 - def addlabel(self, ix, label, info=None):
910 """Add string label to indexed point. info dictionary is optional"""
911 if ix < 0:
912 ix = len(self)+ix
913 if ix in xrange(len(self)):
914 self.labels.update(ix, label, info)
915 else:
916 raise ValueError("Index out of range")
917
918
920 """Remove all labels at indexed point."""
921 del self.labels[ix]
922
923
925 """Return pointset containing points labelled with the supplied
926 labels. Argument s can be a string or a list of strings."""
927 if isinstance(s, str):
928 if s == '':
929 raise ValueError("Label must be non-empty")
930 else:
931 ixlist = sortedDictKeys(self.labels[s])
932 if ixlist != []:
933 return self[ixlist]
934 else:
935 return None
936 elif isinstance(s, list):
937 ixlist = []
938 for ss in s:
939 if isinstance(ss, str):
940 if ss == '':
941 raise ValueError("Label must be non-empty")
942 ixlist = sortedDictKeys(self.labels[ss])
943 else:
944 raise TypeError("Invalid label type")
945 if ixlist != []:
946 return self[ixlist]
947 else:
948 return None
949 else:
950 raise TypeError("Invalid label type")
951
952
953
955 """Change individual points, accessed by index (no slicing supported).
956 Individual coordinate values of a point can be changed by adding a
957 cross-reference coordinate name or index.
958 If ix is a variable name then the entire row can be changed (again,
959 no slicing supported)."""
960 if isinstance(ix, _int_types):
961 if isinstance(p, Point):
962 if compareNumTypes(self.coordtype, int32) and \
963 compareNumTypes(p.coordtype, float64):
964 raise ValueError("Cannot update integer pointset with a float")
965 self.coordarray[:,ix] = p.toarray()
966 if len(p.labels) > 0:
967 self.labels.update({ix: p.labels})
968 elif isinstance(p, dict):
969 vlist = []
970 for k in self.coordnames:
971 vlist.append(p[k])
972 self.coordarray[:,ix] = array(vlist, self.coordtype)
973 elif isinstance(p, _seq_types):
974 self.coordarray[:,ix] = array(p, self.coordtype)
975 else:
976 raise TypeError("Invalid index reference")
977 elif isinstance(ix, tuple) and len(ix) == 2:
978
979 try:
980 c = self._name_ix_map[ix[1]]
981 except KeyError:
982 c = ix[1]
983 if isinstance(p, _int_types):
984 self.coordarray[c,ix[0]] = p
985 elif isinstance(p, _float_types):
986 if self.coordtype == float64:
987 self.coordarray[c,ix[0]] = p
988 else:
989 raise TypeError("Cannot update an integer pointset with a float")
990 elif isinstance(p, ndarray) and p.shape==(1,):
991 self.coordarray[c,ix[0]] = p[0]
992 elif isinstance(p, list) and len(list) == 1:
993 self.coordarray[c,ix[0]] = p[0]
994 elif isinstance(p, Point) and p.dimension == 1:
995 self.coordarray[c,ix[0]] = p[0]
996 if len(p.labels) > 0:
997 self.labels.update({ix: p.labels})
998 else:
999 raise TypeError("New value is not a singleton numeric type")
1000 elif isinstance(ix, str):
1001 if ix == self.indepvarname:
1002 if isinstance(p, Pointset):
1003 if compareNumTypes(self.indepvartype, int32) and \
1004 compareNumTypes(p.indepvartype, float64):
1005 raise ValueError("Cannot update integer independent variable with a float")
1006 if len(self) == len(p):
1007 self.indepvararray = p.toarray()
1008 else:
1009 raise ValueError("Size mismatch for new independent variable array")
1010
1011 elif isinstance(p, dict):
1012 if len(self) == len(p[c]):
1013 self.indepvararray = array(p[c], self.indepvartype)
1014 else:
1015 raise ValueError("Size mismatch for new independent variable array")
1016 elif isinstance(p, _seq_types):
1017 if len(self) == len(p):
1018 self.indepvararray = array(p, self.indepvartype)
1019 else:
1020 raise ValueError("Size mismatch for new independent variable array")
1021 else:
1022 raise TypeError("Invalid data")
1023 elif ix in self.coordnames:
1024 c = self._name_ix_map[ix]
1025 if isinstance(p, Pointset):
1026 if compareNumTypes(self.coordtype, int32) and \
1027 compareNumTypes(p.coordtype, float64):
1028 raise ValueError("Cannot update integer pointset with a float")
1029 self.coordarray[c,:] = p.toarray()
1030
1031 elif isinstance(p, dict):
1032 self.coordarray[c,:] = array(p[c], self.coordtype)
1033 elif isinstance(p, _seq_types):
1034 self.coordarray[c,:] = array(p, self.coordtype)
1035 elif isinstance(p, _real_types):
1036 self.coordarray[c,:] = float(p)
1037 else:
1038 raise TypeError("Invalid data")
1039 else:
1040 raise TypeError("Invalid variable reference")
1041 else:
1042 raise TypeError("Invalid Pointset reference")
1043
1044
1046
1047 if isinstance(ix, _int_types):
1048
1049
1050 if ix < 0:
1051 ix = ix + self.coordarray.shape[1]
1052 if ix in self.labels:
1053 label = self.labels[ix]
1054 else:
1055 label = {}
1056 return Point({'coordarray': self.coordarray[:,ix],
1057 'coordnames': self.coordnames,
1058 'norm': self._normord,
1059 'labels': label})
1060 elif isinstance(ix, tuple):
1061 if len(ix) != 2:
1062 raise ValueError("Only use 2-tuples in referencing pointset")
1063 ref1 = ix[0]
1064 ref2 = ix[1]
1065 elif isinstance(ix, str):
1066
1067 if self._parameterized:
1068 if ix == self.indepvarname:
1069 return self.indepvararray
1070 else:
1071 return self.coordarray[self._map_names_to_ixs(ix),:]
1072 else:
1073 return self.coordarray[self._map_names_to_ixs(ix),:]
1074 elif isinstance(ix, list):
1075 if all([x in self.coordnames for x in ix]):
1076 ref1 = slice(len(self))
1077 ref2 = ix
1078 else:
1079 ref1 = ix
1080 ref2 = None
1081 elif isinstance(ix, (ndarray, slice)):
1082 ref1 = ix
1083 ref2 = None
1084 else:
1085 raise IndexError("Illegal index %s"%str(ix))
1086 if isinstance(ref1, (list, ndarray, _int_types)):
1087 if isinstance(ref1, _int_types):
1088 ref1 = [ref1]
1089 try:
1090 ca = take(self.coordarray, ref1, axis=1)
1091 except ValueError:
1092 raise ValueError("Invalid variable names given: "%(str(ref1)))
1093 try:
1094 ci = take(self.indepvararray, ref1, axis=0)
1095 except (IndexError, AttributeError):
1096
1097 pass
1098 cl = self.labels[ref1]
1099 cl_ixs = cl.getIndices()
1100 ixmap = invertMap(ref1)
1101 new_cl_ixs = [ixmap[i] for i in cl_ixs]
1102 elif isinstance(ref1, slice):
1103 ls = len(self)
1104 if ref1.stop is None:
1105 stop = ls
1106 else:
1107 if ref1.stop < 0:
1108 stop = ref1.stop + self.coordarray.shape[1] + 1
1109 else:
1110 stop = ref1.stop
1111 s1, s2, s3 = ref1.indices(stop)
1112 if s1 < 0 or s2 > ls or s1 >= ls:
1113 raise ValueError("Slice index out of range")
1114 ca = take(self.coordarray, xrange(s1, s2, s3), axis=1)
1115 try:
1116 ci = take(self.indepvararray, xrange(s1, s2, s3),axis=0)
1117 except (IndexError, AttributeError):
1118
1119 pass
1120 cl = self.labels[ref1]
1121 cl_ixs = cl.getIndices()
1122 lowest_ix = ref1.start or 0
1123 if lowest_ix < 0:
1124 lowest_ix = len(self)+lowest_ix
1125 new_cl_ixs = [i-lowest_ix for i in cl_ixs]
1126 else:
1127 print "ref1 argument =", ref1
1128 raise TypeError("Type %s is invalid for Pointset indexing"%str(type(ref1)))
1129 ixlist = self._force_coords_to_ixlist(ref2)
1130 ca = take(ca, ixlist, axis=0)
1131 try:
1132 cl.mapIndices(dict(zip(cl_ixs, new_cl_ixs)))
1133 except AttributeError:
1134 pass
1135 if self._parameterized:
1136 return Pointset({'coordarray': ca,
1137 'coordnames': [self.coordnames[i] for i in ixlist],
1138 'indepvararray': ci,
1139 'indepvarname': self.indepvarname,
1140 'norm': self._normord,
1141 'labels': cl})
1142 else:
1143 return Pointset({'coordarray': ca,
1144 'coordnames': [self.coordnames[i] for i in ixlist],
1145 'norm': self._normord,
1146 'labels': cl})
1147
1148
1150 if self.checklevel == 0:
1151 return self._indepvar_ix_map[p]
1152 else:
1153 try:
1154 return self._indepvar_ix_map[p]
1155 except:
1156 ixs = self.findIndex(p)
1157 lval = self.indepvararray[ixs[0]]
1158 rval = self.indepvararray[ixs[1]]
1159 if p - lval < self._abseps:
1160 return ixs[0]
1161 elif rval - p <= self._abseps:
1162 return ixs[1]
1163 else:
1164 lerr = p - lval
1165 rerr = rval - p
1166 raise KeyError( \
1167 "%f not found in (%f, %f) @tol=%.16f: mismatches=(%.16f, %.16f)"%(p,lval,rval,self._abseps,lerr,rerr))
1168
1169
1171 if tol > 0:
1172 self._abseps = tol
1173 else:
1174 raise ValueError("tolerance must be a positive real number")
1175
1176
1178 if not self._parameterized:
1179 raise TypeError("Cannot call a non-parameterized Pointset")
1180 if isinstance(p, _seq_types):
1181
1182
1183 try:
1184 ix = [self._resolve_indepvar(i) for i in p]
1185 except KeyError:
1186 raise ValueError("Independent variable value not valid: %s"%str(p))
1187 else:
1188
1189 try:
1190 ix = self._resolve_indepvar(p)
1191 except KeyError:
1192 raise ValueError("Independent variable value not valid: " \
1193 + str(p))
1194 if coords is None:
1195 if isinstance(ix, _int_types):
1196 label = self.labels[ix]
1197 try:
1198 label.mapIndices({ix: 0})
1199 except AttributeError:
1200
1201 pass
1202 return Point({'coordarray': self.coordarray[:,ix],
1203 'coordnames': self.coordnames,
1204 'norm': self._normord,
1205 'labels': label})
1206 else:
1207 labels = self.labels[ix]
1208 cl_ixs = labels.getIndices()
1209 ixmap = invertMap(ix)
1210 new_cl_ixs = [ixmap[i] for i in cl_ixs]
1211 if isinstance(ix, slice):
1212 lowest_ix = ix.start or 0
1213 new_cl_ixs = [i-lowest_ix for i in cl_ics]
1214 elif isinstance(ix, (list, ndarray)):
1215 new_cl_ixs = [ixmap[i] for i in cl_ixs]
1216 try:
1217 labels.mapIndices(dict(zip(cl_ixs, new_cl_ixs)))
1218 except AttributeError:
1219
1220 pass
1221 return Pointset({'coordarray': take(self.coordarray, ix, axis=1),
1222 'coordnames': self.coordnames,
1223 'indepvarname': self.indepvarname,
1224 'indepvararray': take(self.indepvararray, ix, axis=0),
1225 'norm': self._normord,
1226 'labels': labels})
1227 else:
1228 clist = self._force_coords_to_ixlist(coords)
1229 if isinstance(ix, _int_types):
1230 label = self.labels[ix]
1231 try:
1232 label.mapIndices({ix: 0})
1233 except AttributeError:
1234
1235 pass
1236 return Point({'coordarray': self.coordarray[clist, ix],
1237 'coordnames': [self.coordnames[i] for i in clist],
1238 'norm': self._normord,
1239 'labels': label})
1240 else:
1241 labels = self.labels[ix]
1242 try:
1243 labels.mapIndices(dict(zip(labels, [i-ix[0] for i in labels.getIndices()])))
1244 except AttributeError:
1245
1246 pass
1247 return Pointset({'coordarray': take(self.coordarray[clist], ix, axis=1),
1248 'coordnames': [self.coordnames[i] for i in clist],
1249 'indepvarname': self.indepvarname,
1250 'indepvararray': take(self.indepvararray, ix, axis=0),
1251 'norm': self._normord,
1252 'labels': labels})
1253
1254
1256 return self.coordarray.shape[1]
1257
1258
1264
1265
1267 if isinstance(other, Pointset):
1268 if not all(self.indepvararray == other.indepvararray):
1269 raise ValueError("Independent variable arrays are not the same")
1270 return array([self[i] < other[i] for i in range(len(self))], 'Bool')
1271 elif isinstance(other, Point):
1272 return array([p < other for p in self], 'Bool')
1273 else:
1274 try:
1275 return self.coordarray < other
1276 except:
1277 raise TypeError("Invalid type for comparison with Pointset")
1278
1280 if isinstance(other, Pointset):
1281 if not all(self.indepvararray == other.indepvararray):
1282 raise ValueError("Independent variable arrays are not the same")
1283 return array([self[i] > other[i] for i in range(len(self))], 'Bool')
1284 elif isinstance(other, Point):
1285 return array([p > other for p in self], 'Bool')
1286 else:
1287 try:
1288 return self.coordarray > other
1289 except:
1290 raise TypeError("Invalid type for comparison with Pointset")
1291
1293 if isinstance(other, Pointset):
1294 if not all(self.indepvararray == other.indepvararray):
1295 raise ValueError("Independent variable arrays are not the same")
1296 return array([self[i] <= other[i] for i in range(len(self))], 'Bool')
1297 elif isinstance(other, Point):
1298 return array([p <= other for p in self], 'Bool')
1299 else:
1300 try:
1301 return self.coordarray <= other
1302 except:
1303 raise TypeError("Invalid type for comparison with Pointset")
1304
1306 if isinstance(other, Pointset):
1307 if not all(self.indepvararray == other.indepvararray):
1308 raise ValueError("Independent variable arrays are not the same")
1309 return array([self[i] >= other[i] for i in range(len(self))], 'Bool')
1310 elif isinstance(other, Point):
1311 return array([p >= other for p in self], 'Bool')
1312 else:
1313 try:
1314 return self.coordarray >= other
1315 except:
1316 raise TypeError("Invalid type for comparison with Pointset")
1317
1319 if isinstance(other, Pointset):
1320 if not all(self.indepvararray == other.indepvararray):
1321 raise ValueError("Independent variable arrays are not the same")
1322 return array([self[i] == other[i] for i in range(len(self))], 'Bool')
1323 elif isinstance(other, Point):
1324 return array([p == other for p in self], 'Bool')
1325 else:
1326 try:
1327 return self.coordarray == other
1328 except:
1329 raise TypeError("Invalid type for comparison with Pointset")
1330
1332 if isinstance(other, Pointset):
1333 if not all(self.indepvararray == other.indepvararray):
1334 raise ValueError("Independent variable arrays are not the same")
1335 return array([self[i] != other[i] for i in range(len(self))], 'Bool')
1336 elif isinstance(other, Point):
1337 return array([p != other for p in self], 'Bool')
1338 else:
1339 try:
1340 return self.coordarray != other
1341 except:
1342 raise TypeError("Invalid type for comparison with Pointset")
1343
1344
1345 - def insert(self, parg, ix=None):
1346 """Insert individual Point or Pointset before the given index.
1347
1348 If ix is not given then the source and target Pointsets must
1349 be parameterized. In this case the Point or Pointset will be
1350 inserted according to the ordering of independent variable
1351 values."""
1352 p=copy(parg)
1353 if ix is None:
1354 if self._parameterized:
1355 if isinstance(p, Point) and self.indepvarname in p.coordnames:
1356 t = p[self.indepvarname]
1357 tix = self.find(t)
1358 if isinstance(tix, tuple):
1359 self.insert(p, tix[1])
1360 else:
1361
1362
1363 raise ValueError("Point at independent variable"
1364 "value %f already present"%t)
1365 elif isinstance(p, Pointset) and p._parameterized and \
1366 p.indepvarname == self.indepvarname:
1367
1368
1369
1370
1371
1372 iva = self.indepvararray.tolist()
1373 vd = self.todict(aslist=True)
1374
1375
1376
1377 if len(intersect(self._ix_name_map, p._ix_name_map)) != self.dimension:
1378 raise ValueError("Dimension mismatch with inserted Pointset")
1379 iva_p = p.indepvararray
1380 lenp = len(p)
1381 vd_p = p.todict()
1382 try:
1383 s_ixs = [self.findIndex(iva_p[i])[1]+i for i in xrange(lenp)]
1384 except TypeError:
1385 raise ValueError("Independent variable "
1386 "values in Pointset already present")
1387 p_label_ixs = p.labels.getIndices()
1388 s_label_ixs = self.labels.getIndices()
1389 sLabelMap = {}
1390 pLabelMap = {}
1391 for i in xrange(lenp):
1392 s_ix = s_ixs[i]
1393 if i in p_label_ixs:
1394 pLabelMap[i] = s_ix
1395 for s_label_ix in s_label_ixs:
1396 if s_label_ix >= s_ix-i:
1397 sLabelMap[s_label_ix] = s_label_ix+i+1
1398
1399 for p_ix in xrange(lenp):
1400 s_ix = s_ixs[p_ix]
1401 iva.insert(s_ix, iva_p[p_ix])
1402 for k in self._ix_name_map:
1403 vd[k].insert(s_ix, vd_p[k][p_ix])
1404
1405 self.indepvararray = array(iva)
1406 datalist = []
1407 for c in p._ix_name_map:
1408 datalist.append(vd[c])
1409 self.coordarray = array(datalist, self.coordtype)
1410
1411 self.labels.mapIndices(sLabelMap)
1412 p_labels = copy(p.labels)
1413 p_labels.mapIndices(pLabelMap)
1414 self.labels.update(p_labels)
1415 else:
1416 raise TypeError("Inserted Point/Pointset must be "
1417 "parameterized and share same independent"
1418 "parameter name")
1419 else:
1420 raise TypeError("Source Pointset must be parameterized")
1421 else:
1422 if ix > 0:
1423 p_result = copy(self[:ix])
1424 p_result.append(p)
1425 else:
1426 p_result = pointsToPointset(p, self.indepvarname)
1427 try:
1428 p_result.append(self[ix:])
1429 except ValueError:
1430
1431
1432 pass
1433 self.coordarray = p_result.coordarray
1434 self.labels = p_result.labels
1435 self.indepvararray = p_result.indepvararray
1436 self.makeIxMaps()
1437
1438
1439 - def append(self, parg, t=None, skipMatchingIndepvar=False):
1440 """Append individual Point or Pointset in place.
1441
1442 skipMatchingIndepvar option causes a matching independent
1443 variable value at the beginning of p to be skipped (only
1444 meaningful for appending parameterized Pointsets). This
1445 option is mainly for internal use."""
1446
1447
1448
1449 p = copy(parg)
1450 if isinstance(p, Pointset):
1451 assert p._parameterized == self._parameterized, "Parameterization mismatch"
1452
1453 if compareNumTypes(self.coordtype, int32) and \
1454 compareNumTypes(p.coordtype, float64):
1455 raise TypeError("Cannot add float64 pointset to an int32 Pointset")
1456 pdim = p.dimension
1457 if self._parameterized:
1458 if t is None:
1459 if self.indepvarname in p.coordnames:
1460 t = p[self.indepvarname]
1461 pdim = pdim - 1
1462 elif self.indepvarname == p.indepvarname:
1463 t = p.indepvararray
1464 else:
1465 raise ValueError("Independent variable missing from Pointset")
1466 if t[0] == self.indepvararray[-1] and skipMatchingIndepvar:
1467 tval = t[1:]
1468 start_ix = 1
1469 else:
1470 tval = t
1471 start_ix = 0
1472 if len(tval) > 0 and tval[0] <= self.indepvararray[-1]:
1473
1474 raise ValueError("Independent variable value too small to add pointset")
1475 added_len = len(tval)
1476 else:
1477 if t[0] == self.indepvararray[-1] and skipMatchingIndepvar:
1478 tval = t[1:]
1479 start_ix = 1
1480 else:
1481 tval = t[:]
1482 start_ix = 0
1483 if len(tval) > 0 and tval[0] <= self.indepvararray[-1]:
1484
1485 raise ValueError("Independent variable value too small to add pointset")
1486 added_len = len(tval)
1487 else:
1488 if t is not None:
1489 raise TypeError("t argument cannot be used for non-parameterized pointsets")
1490 added_len = p.coordarray.shape[1]
1491 start_ix = 0
1492 assert pdim == self.dimension, "Dimension mismatch with Pointset"
1493 if pdim < p.dimension:
1494 pcoords = copy(p.coordnames)
1495 pcoords.remove(p.indepvarname)
1496 else:
1497 pcoords = p.coordnames
1498 if remain(pcoords, self.coordnames) != []:
1499 raise ValueError("Coordinate name mismatch with Pointset")
1500 old_len = self.coordarray.shape[1]
1501 new_len = old_len + added_len
1502 old_coords = self.coordarray
1503 self.coordarray = zeros((self.dimension, new_len),
1504 self.coordarray.dtype)
1505 if self._parameterized:
1506 self.indepvararray.resize(new_len)
1507 tvals = tval[range(added_len)]
1508 self.indepvararray[old_len:] = tvals
1509 for tix in xrange(old_len):
1510 self.coordarray[:, tix] = old_coords[:, tix]
1511 pdict = p.todict()
1512 self.coordarray[:, old_len:] = r_[[pdict[c][start_ix:] for c in self._ix_name_map]]
1513 p_labels = copy(p.labels)
1514 pixs = p.labels.getIndices()
1515 if start_ix == 1:
1516 p_labels.mapIndices(dict(zip(pixs, [i+old_len-1 for i in pixs])))
1517 else:
1518 p_labels.mapIndices(dict(zip(pixs, [i+old_len for i in pixs])))
1519 self.labels.update(p_labels)
1520 elif isinstance(p, Point):
1521
1522 if compareNumTypes(self.coordtype, int32) and \
1523 compareNumTypes(p.coordtype, float64):
1524 raise TypeError("Cannot add float64 Point to an int32 Pointset")
1525 pdim = p.dimension
1526 if self._parameterized:
1527 if t is None:
1528 if self.indepvarname not in p.coordnames:
1529 raise ValueError("Independent variable missing from Point")
1530 else:
1531 tval = p[self.indepvarname]
1532 if tval <= self.indepvararray[-1]:
1533 raise ValueError("Independent variable value too small to add Point")
1534 pdim = pdim - 1
1535 else:
1536 if t <= self.indepvararray[-1]:
1537 raise ValueError("Independent variable value too small to add Point")
1538 tval = t
1539 elif t is not None:
1540 raise TypeError("t argument cannot be used for non-parameterized Pointsets")
1541 assert pdim == self.dimension, "Dimension mismatch with Point"
1542 if pdim < p.dimension:
1543 pcoords = copy(p.coordnames)
1544 if self._parameterized:
1545 pcoords.remove(self.indepvarname)
1546 else:
1547 pcoords = p.coordnames
1548 if remain(pcoords, self.coordnames) != []:
1549 raise ValueError("Coordinate name mismatch with Point")
1550 new_len = self.coordarray.shape[1]+1
1551 old_coords = self.coordarray
1552 self.coordarray = zeros((self.dimension, new_len), self.coordarray.dtype)
1553 if self._parameterized:
1554 self.indepvararray.resize(new_len)
1555 self.indepvararray.resize(new_len)
1556 self.indepvararray[new_len-1] = tval
1557 for tix in xrange(new_len-1):
1558 self.coordarray[:, tix] = old_coords[:, tix]
1559 for ix in xrange(self.dimension):
1560 self.coordarray[ix,new_len-1] = p(self._ix_name_map[ix])
1561 if len(p.labels) > 0:
1562 self.labels.update({new_len-1: p.labels})
1563 else:
1564 raise TypeError("append requires Point or Pointset argument")
1565 self.makeIxMaps()
1566
1567
1568 extend = append
1569
1570
1571 - def toarray(self, include_indepvar=False):
1572 """Convert the pointset to a D x L array (one variable per row),
1573 where D is the dimension of the pointset and L is its length.
1574 (This is a copy of the internal attribute 'coordarray'.)
1575
1576 If the optional include_indepvar switch is set True (default False),
1577 the first row is the independent variable, and the whole
1578 array will be (D+1) x L in shape.
1579 """
1580 if self.dimension==1:
1581 ca = copy(self.coordarray[0])
1582 else:
1583 ca = copy(self.coordarray)
1584 if include_indepvar:
1585 ia = copy(self.indepvararray)
1586 ia.shape = (1, len(ia))
1587 return concatenate((ia,ca))
1588 else:
1589 return ca
1590
1591
1592 - def todict(self, aslist=False):
1593 """Convert Pointset to a dictionary of arrays (or of lists with aslist=True)."""
1594 if aslist:
1595 d = dict(zip(self._ix_name_map, self.coordarray.tolist()))
1596 else:
1597 d = dict(zip(self._ix_name_map, self.coordarray))
1598 if self._parameterized:
1599 d[self.indepvarname] = self.indepvararray
1600 return d
1601
1602
1604 if self.name == '':
1605 outputStr = "Pointset <no name>"
1606 else:
1607 outputStr = "Pointset " + self.name
1608 if self._parameterized:
1609 outputStr += " (parameterized)"
1610 else:
1611 outputStr += " (non-parameterized)"
1612 if verbose > 0:
1613 precision = 8
1614 lenv = len(self)
1615 if lenv > 8:
1616 ixslo = range(0,2)
1617 ixshi = range(lenv-2,lenv)
1618 outputStr += "\n"
1619 if self._parameterized:
1620 iv = self.indepvararray
1621 if not isinstance(iv, ndarray):
1622 iv = array(iv, self.indepvartype)
1623 if lenv > 8:
1624 alo = array2string(iv[ixslo],precision=precision)
1625 ahi = array2string(iv[ixshi],precision=precision)
1626 ivstr = alo[:-1] + ", ..., " + ahi[1:]
1627 else:
1628 ivstr = array2string(iv,precision=precision)
1629 outputStr += "Independent variable:\n"
1630 outputStr += self.indepvarname + ': '+ivstr+"\n"
1631 outputStr += "Coordinates:\n"
1632 for c in self.coordnames:
1633 v = self.coordarray[self._map_names_to_ixs(c)]
1634 if not isinstance(v, ndarray):
1635
1636 v = array([v], self.coordtype)
1637 if lenv > 8:
1638 alo = array2string(v[ixslo],precision=precision)
1639 ahi = array2string(v[ixshi],precision=precision)
1640 dvstr = alo[:-1] + ", ..., " + ahi[1:]
1641 else:
1642 dvstr = array2string(v, precision=precision)
1643 outputStr += c+': '+dvstr
1644 if c != self.coordnames[-1]:
1645 outputStr += "\n"
1646 outputStr += "\nLabels by index: " + self.labels._infostr(17)
1647 return outputStr
1648
1649
1652
1653
1656
1657
1658 - def info(self, verboselevel=1):
1660
1661
1663 if self._parameterized:
1664 return Pointset({'coordarray': copy(self.coordarray),
1665 'coordnames': copy(self.coordnames),
1666 'indepvarname': copy(self.indepvarname),
1667 'indepvararray': copy(self.indepvararray),
1668 'norm': self._normord,
1669 'labels': copy(self.labels)
1670 })
1671 else:
1672 return Pointset({'coordarray': copy(self.coordarray),
1673 'coordnames': copy(self.coordnames),
1674 'norm': self._normord,
1675 'labels': copy(self.labels)})
1676
1677 copy = __copy__
1678
1679
1681 d = copy(self.__dict__)
1682
1683 try:
1684 d['indepvartype'] = _num_type2name[self.indepvartype]
1685 except KeyError:
1686
1687 pass
1688 d['coordtype'] = _num_type2name[self.coordtype]
1689 return d
1690
1691
1693 self.__dict__.update(state)
1694
1695 try:
1696 self.indepvartype = _num_name2type[self.indepvartype]
1697 except KeyError:
1698
1699 pass
1700 self.coordtype = _num_name2type[self.coordtype]
1701
1703 """Verifies the matching of independent variable arrays in two pointsets.
1704 Does nothing if either object is not a parameterized pointset."""
1705 try:
1706 if other._parameterized and self._parameterized:
1707 if not all(self.indepvararray == other.indepvararray):
1708 print self.indepvararray
1709 print other.indepvararray
1710 raise ValueError("Mismatched independent variable arrays")
1711 except AttributeError:
1712 pass
1713
1717
1721
1725
1729
1733
1737
1741
1745
1746 - def find(self, indepval, end=None):
1747 """find returns an integer index for where to place
1748 a point having independent variable value <indepval> in
1749 the Pointset, if <indepval> already exists. Otherwise, a
1750 pair indicating the nearest independent variable values
1751 present in the Pointset is returned.
1752
1753 To ensure an integer is always returned, choose a left or
1754 right side to choose from the pair, using end=0 or 1 respectively."""
1755 if not self._parameterized:
1756 raise TypeError("Cannot find index from independent variable for "
1757 "a non-parameterized Pointset")
1758 try:
1759 ix = self.indepvararray.tolist().index(indepval)
1760 result = ix
1761 except ValueError:
1762 cond = less(self.indepvararray, indepval).tolist()
1763 try:
1764 ix = cond.index(0)
1765 result = (ix-1, ix)
1766 except ValueError:
1767 result = (len(self.indepvararray)-1, len(self.indepvararray))
1768 if end is not None:
1769 result = result[end]
1770 return result
1771
1772
1773 findIndex = find
1774
1775
1776
1777
1778
1780 """Structure for storing individual point labels and information
1781 dictionaries within a Pointset object.
1782
1783 This class will not know the size of the Pointset it is associated with,
1784 so index upper limits will not be checked in advance.
1785
1786 Do not use a PointInfo object as an iterator, as it is 'infinite' in size!
1787 (It uses DefaultDicts as its internal storage, which return {} for
1788 undefined labels.)"""
1789
1791 if ptlabels is None:
1792 self.by_label = DefaultDict({})
1793 self.by_index = DefaultDict({})
1794 elif isinstance(ptlabels, PointInfo):
1795 self.by_label = ptlabels.by_label
1796 self.by_index = ptlabels.by_index
1797 elif isinstance(ptlabels, dict):
1798
1799 self.by_label = DefaultDict({})
1800 self.by_index = DefaultDict({})
1801 for k, v in ptlabels.iteritems():
1802 if not isinstance(k, _int_types):
1803 raise TypeError("Initialization dictionary must be keyed "
1804 "by integer indices")
1805 if isinstance(v, str):
1806 self.by_label[v][k] = {}
1807 self.by_index[k][v] = {}
1808 else:
1809 for label, infodict in v.iteritems():
1810 self.by_label[label][k] = infodict
1811 self.by_index[k][label] = infodict
1812 else:
1813 raise TypeError("Invalid labels at initialization of PointInfo")
1814
1815
1817 by_index = {}
1818 ixMap = symbolMapClass(ixMapDict)
1819 for ix, rest in self.by_index.iteritems():
1820 by_index[ixMap(ix)] = rest
1821 self.__init__(by_index)
1822
1823
1825 """Map labels, using a symbol map of class symbolMapClass."""
1826 self.by_label = mapNames(themap, self.by_label)
1827 new_by_index = {}
1828 for ix, labdict in self.by_index.iteritems():
1829 new_by_index[ix] = mapNames(themap, labdict)
1830 self.by_index = new_by_index
1831
1832
1834 ixkeys = sortedDictKeys(self.by_index)
1835 return zip(ixkeys,[self.by_index[ix] for ix in ixkeys])
1836
1837
1839 labelkeys = sortedDictKeys(self.by_label)
1840 return zip(labelkeys,[self.by_label[label] for label in labelkeys])
1841
1842
1845
1846
1849
1850
1852 return key in self.by_index or key in self.by_label
1853
1854
1856
1857
1858
1859
1860 if isinstance(key, tuple):
1861 raise TypeError("Can only reference PointInfo with a single key")
1862 else:
1863 if isinstance(key, (slice, list, ndarray)):
1864 if isinstance(key, slice):
1865 self_ixs = self.getIndices()
1866 if len(self_ixs) == 0:
1867 max_ixs = 0
1868 else:
1869 max_ixs = max(self_ixs)
1870 stop = key.stop or max_ixs+1
1871 try:
1872 s1, s2, s3 = key.indices(stop)
1873 ixs = xrange(s1, s2, s3)
1874 key = intersect(ixs, self_ixs)
1875 except TypeError:
1876 key = self_ixs
1877 else:
1878 if all([isinstance(k, str) for k in key]):
1879 keylabels = intersect(key, self.getLabels())
1880 key = []
1881 for l in keylabels:
1882 key.extend(self.by_label[l].keys())
1883 key = makeSeqUnique(key)
1884 elif all([isinstance(k, _int_types) for k in key]):
1885 key = intersect(key, self.getIndices())
1886 else:
1887 raise TypeError("Invalid key type for PointInfo")
1888 return PointInfo(dict(zip(key,[self.by_index[i] for i in key])))
1889 elif key in self.by_index:
1890 return self.by_index[key]
1891 elif key in self.by_label:
1892 return self.by_label[key]
1893 elif isinstance(key, int) and key < 0:
1894 raise IndexError("Cannot use negative indices for PointInfo")
1895 else:
1896 return {}
1897
1898
1900 if isinstance(the_rest, tuple) and len(the_rest) == 2:
1901 if isinstance(the_rest[0], str):
1902 label = the_rest[0]
1903 ix = None
1904 elif isinstance(the_rest[0], _int_types):
1905 ix = the_rest[0]
1906 label = None
1907 else:
1908 raise TypeError("String expected for label")
1909 if isinstance(the_rest[1], dict):
1910 info = copy(the_rest[1])
1911 else:
1912 raise TypeError("Dictionary expected for info")
1913 elif isinstance(the_rest, str):
1914 label = the_rest
1915 ix = None
1916 info = {}
1917 elif isinstance(the_rest, _int_types):
1918 ix = the_rest
1919 label = None
1920 info = {}
1921 elif isinstance(the_rest, list):
1922 self.__setitem__(key1, the_rest[0])
1923 for item in the_rest[1:]:
1924 if isinstance(item, tuple) and len(item) == 2:
1925 self.update(key1, item[0], item[1])
1926 else:
1927 self.update(key1, item)
1928 return
1929 else:
1930 raise TypeError("Invalid item to set in PointInfo")
1931 if isinstance(key1, _int_types):
1932 if label is None:
1933 raise TypeError("Label expected")
1934 ix = key1
1935 elif isinstance(key1, str):
1936 if ix is None:
1937 raise TypeError("Index expected")
1938 label = key1
1939 if ix < 0:
1940 raise IndexError("Index must be non-negative")
1941 try:
1942 self.by_label[label].update({ix: info})
1943 except KeyError:
1944 self.by_label[label] = {ix: info}
1945 try:
1946 self.by_index[ix].update({label: info})
1947 except KeyError:
1948 self.by_index[ix] = {label: info}
1949
1950
1952 return len(self.by_index)
1953
1954
1955 - def remove(self, key1, *key2):
1956 """remove one or more items, keyed either by index or label."""
1957 byix = key1 in self.by_index
1958 if key2 == ():
1959
1960 if byix:
1961 key2 = self.by_index[key1].keys()
1962 else:
1963 key2 = self.by_label[key1].keys()
1964 if byix:
1965 for k in key2:
1966
1967 if k in self.by_label:
1968 del self.by_index[key1][k]
1969 del self.by_label[k][key1]
1970 else:
1971 raise KeyError("Label not found")
1972 if self.by_label[k] == {}:
1973 del self.by_label[k]
1974 if self.by_index[key1] == {}:
1975 del self.by_index[key1]
1976 else:
1977 for k in key2:
1978
1979 if k in self.by_index:
1980 del self.by_index[k][key1]
1981 del self.by_label[key1][k]
1982 else:
1983 raise KeyError("Index not found")
1984 if self.by_index[k] == {}:
1985 del self.by_index[k]
1986 if self.by_label[key1] == {}:
1987 del self.by_label[key1]
1988
1989
1990 - def update(self, key1, key2=None, info=None):
1991 if isinstance(key1, PointInfo):
1992 if key2 is None and info is None:
1993 for k, v in key1.by_index.iteritems():
1994 for vk, vv in v.iteritems():
1995 self.update(k, vk, vv)
1996 else:
1997 raise TypeError("Invalid calling sequence to update")
1998 elif isinstance(key1, dict):
1999 if key2 is None and info is None:
2000 for k, v in key1.iteritems():
2001 if isinstance(k, _int_types):
2002 if k < 0:
2003 k = k + len(self.by_index)
2004 if isinstance(v, str):
2005 k2 = v
2006 k3 = {}
2007 self.update(k, k2, k3)
2008 elif isinstance(v, tuple) and len(v)==2:
2009 k2 = v[0]
2010 k3 = v[1]
2011 self.update(k, k2, k3)
2012 elif isinstance(v, dict):
2013 for k2, k3 in v.iteritems():
2014 self.update(k, k2, k3)
2015 else:
2016 raise ValueError("Invalid data for update")
2017 else:
2018 raise TypeError("Invalid index for label")
2019 else:
2020 raise TypeError("Invalid calling sequence to update")
2021 elif isinstance(key1, _int_types):
2022 if info is None:
2023 info = {}
2024 if key1 in self.by_index:
2025 if key2 in self.by_index[key1]:
2026 self.by_index[key1][key2].update(info)
2027 else:
2028 self.__setitem__(key1, (key2, info))
2029 else:
2030 self.__setitem__(key1, (key2, info))
2031 elif isinstance(key1, str):
2032 if info is None:
2033 info = {}
2034 if key1 in self.by_label:
2035 if key2 in self.by_label[key1]:
2036 self.by_label[key1][key2].update(info)
2037 else:
2038 self.__setitem__(key2, (key1, info))
2039 else:
2040 self.__setitem__(key2, (key1, info))
2041 else:
2042 raise TypeError("Invalid type for update")
2043
2044
2046 if key in self.by_index:
2047 labels = self.by_index[key].keys()
2048 del self.by_index[key]
2049 for label in labels:
2050 del self.by_label[label][key]
2051 if self.by_label[label] == {}:
2052 del self.by_label[label]
2053 elif key in self.by_label:
2054 ixs = self.by_label[key].keys()
2055 del self.by_label[key]
2056 for ix in ixs:
2057 del self.by_index[ix][key]
2058 if self.by_index[ix] == {}:
2059 del self.by_index[ix]
2060 else:
2061 raise KeyError("Index or label not found")
2062
2063
2065 try:
2066 return all(self.by_index.keys() == other.by_index.keys()) and \
2067 all(self.by_label.keys() == other.by_label.keys())
2068 except AttributeError:
2069 raise TypeError("Invalid type for comparison to PointInfo")
2070
2071
2073 return not self.__eq__(other)
2074
2076 lenself = len(self)
2077 tabstr = " "*tab
2078 basestr = ",\n"+tabstr
2079 if lenself > 0:
2080 entries = self.sortByIndex()
2081 if lenself > 8:
2082 return basestr.join([_pretty_print_label(i) for i in entries[0:3]]) + ",\n" +\
2083 (tabstr + " .\n")*3 + tabstr +\
2084 basestr.join([_pretty_print_label(i) for i in entries[-3:]])
2085 else:
2086 return basestr.join([_pretty_print_label(i) for i in entries])
2087 else:
2088 return "Empty"
2089
2090
2093
2094 __str__ = __repr__
2095
2096
2098 """Internal utility to pretty print point label info."""
2099 s = " %s: "%repr(d[0])
2100 entry_keys = d[1].keys()
2101 ki = 0
2102 kimax = len(entry_keys)
2103 for k in entry_keys:
2104 keys = d[1][k].keys()
2105 if len(keys) == 0:
2106 s += "{%s: {}}"%k
2107 else:
2108 s += "{%s: {keys=%s}}"%(k,",".join(keys))
2109 if ki < kimax-1:
2110 s += ', '
2111 ki += 1
2112 return s
2113
2114
2115
2116
2118 """Compare two Points, Pointsets, or dictionary of point data, coordinate-wise.
2119 If p1 or p2 are Pointsets, their independent variable values, if present, are
2120 *not* compared.
2121
2122 fussy option causes point norm order and coordinate types to be
2123 checked too (requires both arguments to be Points or Pointsets).
2124 """
2125 try:
2126 p1d = dict(p1)
2127 p1dk = p1d.keys()
2128 p2d = dict(p2)
2129 p2dk = p2d.keys()
2130 except:
2131 raise TypeError("Invalid Points, Pointsets, or dictionaries passed "
2132 "to comparePointCoords")
2133 test1 = alltrue([ks[0]==ks[1] for ks in zip(p1dk, p2dk)])
2134 test2 = alltrue([vs[0]==vs[1] for vs in \
2135 zip([p1d[k] for k in p1dk], [p2d[k] for k in p2dk])])
2136 if fussy:
2137 try:
2138 test3 = p1._normord == p2._normord
2139 test4 = compareNumTypes(p1.coordtype, p2.coordtype)
2140 return test1 and test2 and test3 and test4
2141 except AttributeError:
2142 raise TypeError("Invalid Points, Pointsets, or dictionaries passed "
2143 "to comparePointCoords with fussy option")
2144 else:
2145 return test1 and test2
2146
2147
2149 """Returns True if Point or Pointset p is parameterized, False otherwise"""
2150 return p._parameterized
2151
2152
2154 """Return a new Pointset stripped of its parameterization.
2155 """
2156 if isinstance(p, Pointset) and p._isparameterized:
2157 return Pointset({'coordarray': copy(p.coordarray),
2158 'coordnames': copy(p.coordnames),
2159 'norm': p._normord,
2160 'labels': copy(p.labels)})
2161 else:
2162 raise TypeError("Must provide a parameterized Pointset")
2163
2164
2165 -def pointsToPointset(pointlist, indepvarname='', indepvararray=None,
2166 indepvartype=float, norm=2):
2167 """Generate a Pointset from a list of Point objects (or a singleton Point).
2168
2169 Include a name for the independent variable if constructing a
2170 parameterized pointset. The independent variable should be a
2171 coordinate of the Points passed, otherwise it can be passed as the
2172 optional third argument.
2173 """
2174
2175 if not isinstance(indepvarname, str):
2176 raise TypeError("String expected for independent variable name")
2177 if isinstance(pointlist, Point):
2178 pointlist = [pointlist]
2179 coordnames = []
2180 ptype = ''
2181 paramd = indepvarname != ""
2182 if not paramd and indepvararray is not None:
2183 raise ValueError("Must supply independent variable name for "
2184 "parameterized Pointset")
2185 if paramd and indepvararray is None:
2186 iv = []
2187 i = 0
2188 labels = {}
2189 for p in pointlist:
2190 assert isinstance(p, Point), \
2191 "pointlist argument must only contain Points"
2192 if coordnames == []:
2193 ptype = p.coordtype
2194 pdim = p.dimension
2195 coordnames = p.coordnames
2196 xcoordnames = copy(coordnames)
2197 if paramd and indepvararray is None:
2198 assert indepvarname in coordnames, \
2199 "Independent variable name missing"
2200 del xcoordnames[xcoordnames.index(indepvarname)]
2201 dv = {}.fromkeys(xcoordnames)
2202 for c in xcoordnames:
2203 dv[c] = []
2204 if p.labels != {}:
2205 labels.update({0: p.labels})
2206 i += 1
2207 else:
2208
2209 if compareNumTypes(ptype, int32):
2210 if compareNumTypes(p.coordtype, float64):
2211 ptype = float64
2212 elif compareNumTypes(p.coordtype, int32):
2213 pass
2214 else:
2215 raise TypeError("Type mismatch in points")
2216 elif compareNumTypes(ptype, float64):
2217 if not compareNumTypes(p.coordtype, (float64, int32)):
2218 raise TypeError("Type mismatch in points")
2219 else:
2220 raise TypeError("Type mismatch in points")
2221 assert pdim == p.dimension, "Dimension mismatch in points"
2222 if remain(coordnames,p.coordnames) != []:
2223 raise ValueError("Coordinate name mismatch in points")
2224 if p.labels != {}:
2225 labels.update({i: p.labels})
2226 i += 1
2227 for c in xcoordnames: dv[c].append(p(c))
2228 if paramd and indepvararray is None:
2229 iv.append(p(indepvarname))
2230
2231 dim = len(xcoordnames)
2232 ca = array([dv[c] for c in xcoordnames], ptype)
2233 argDict = {'coordarray': ca,
2234 'coordnames': xcoordnames,
2235 'coordtype': ptype,
2236 'labels': labels,
2237 'norm': norm
2238 }
2239 if paramd:
2240 if indepvararray is None:
2241 indepvararray = array(iv, ptype)
2242 argDict.update({'indepvarname': indepvarname,
2243 'indepvararray': indepvararray,
2244 'indepvartype': indepvartype})
2245 return Pointset(argDict)
2246
2247
2249 """Convert an array to a non-parameterized Pointset. The inclusion of an
2250 optional independent variable array creates a parameterized Pointset.
2251
2252 Coordinate (and independent variable) names are optional: the defaults are
2253 the array indices (and 't' for the independent variable).
2254 """
2255 if rank(a) > 2:
2256 raise ValueError("Cannot convert arrays of rank > 2")
2257 if rank(a) == 0:
2258 raise ValueError("Cannot convert arrays of rank 0")
2259 if vnames is None:
2260 vnames = [str(i) for i in range(shape(a)[0])]
2261 else:
2262 if len(vnames) != shape(a)[0]:
2263 raise ValueError("Mismatch between number of coordinate names and"
2264 " number of rows in array.\nCoordinates are "
2265 "assumed to be the rows of the array")
2266 if ia is None:
2267 assert iname=="", ("Independent variable name must be none if no "
2268 "independent variable array provided")
2269 return Pointset({'coordarray': a,
2270 'coordnames': vnames})
2271 else:
2272 if iname == "":
2273 iname = "t"
2274 return Pointset({'coordarray': a,
2275 'coordnames': vnames,
2276 'indepvararray': ia,
2277 'indepvarname': iname})
2278
2279 -def exportPointset(thepointset, infodict, separator=' ',
2280 precision=12, varvaldir='col',
2281 ext='', append=False):
2282 """Export a pointset to a set of ASCII whitespace- (or
2283 user-defined character-) separated data files. Option to list each
2284 variable's data in rows ('across') or in columns ('down').
2285 Existing files of the same names will be overwritten, unless the
2286 'append' boolean option is set.
2287
2288 NB. If the file extension argument 'ext' is present without a
2289 leading dot, one will be added.
2290
2291 infodict should consist of: keys = filenames, values = tuples of
2292 pointset variable names to export.
2293 """
2294 assert varvaldir in ['col', 'row'], \
2295 "invalid variable value write direction"
2296
2297
2298
2299 try:
2300 thepointset.coordnames
2301 except AttributeError:
2302 raise TypeError("Must pass Pointset to this function: use "
2303 "arrayToPointset first!")
2304 infodict_usedkeys = []
2305 for key, info in infodict.iteritems():
2306 if isinstance(info, str):
2307 infodict_usedkeys += [info]
2308 elif info == []:
2309 infodict[key] = copy.copy(thepointset.coordnames)
2310 infodict_usedkeys.extend(thepointset.coordnames)
2311 else:
2312 infodict_usedkeys += list(info)
2313 allnames = copy(thepointset.coordnames)
2314 if thepointset._parameterized:
2315 allnames.append(thepointset.indepvarname)
2316 remlist = remain(infodict_usedkeys, allnames+range(len(allnames)))
2317 if remlist != []:
2318 print "Coords not found in pointset:", remlist
2319 raise ValueError("invalid keys in infodict - some not present "
2320 "in thepointset")
2321 assert isinstance(ext, str), "'ext' extension argument must be a string"
2322 if ext != '':
2323 if ext[0] != '.':
2324 ext = '.'+ext
2325 if append:
2326 assert varvaldir == 'col', ("append mode not supported for row"
2327 "format of data ordering")
2328 modestr = 'a'
2329 else:
2330 modestr = 'w'
2331 totlen = len(thepointset)
2332 if totlen == 0:
2333 raise ValueError("Pointset is empty")
2334 for fname, tup in infodict.iteritems():
2335 try:
2336 f = open(fname+ext, modestr)
2337 except IOError:
2338 print "There was a problem opening file "+fname+ext
2339 raise
2340 try:
2341 if isinstance(tup, str):
2342 try:
2343 varray = thepointset[tup]
2344 except TypeError:
2345 raise ValueError("Invalid specification of coordinates")
2346 elif isinstance(tup, int):
2347 try:
2348 varray = thepointset[:,tup].toarray()
2349 except TypeError:
2350 raise ValueError("Invalid specification of coordinates")
2351 elif isinstance(tup, (list, tuple)):
2352 if alltrue([isinstance(ti,str) for ti in tup]):
2353 thetup=list(tup)
2354 if thepointset.indepvarname in tup:
2355 tix = thetup.index(thepointset.indepvarname)
2356 thetup.remove(thepointset.indepvarname)
2357 try:
2358 vlist = thepointset[thetup].toarray().tolist()
2359 except TypeError:
2360 raise ValueError("Invalid specification of coordinates")
2361 if len(thetup)==1:
2362 vlist = [vlist]
2363 if thepointset.indepvarname in tup:
2364 vlist.insert(tix, thepointset.indepvararray.tolist())
2365 varray = array(vlist)
2366 elif alltrue([isinstance(ti,_int_types) for ti in tup]):
2367 try:
2368 varray = thepointset[:,tup].toarray()
2369 except TypeError:
2370 raise ValueError("Invalid specification of coordinates")
2371 else:
2372 raise ValueError("Invalid specification of coordinates")
2373 else:
2374 f.close()
2375 raise TypeError("infodict values must be singletons or "
2376 "tuples/lists of strings or integers")
2377 except IOError:
2378 f.close()
2379 print "Problem writing to file"+fname+ext
2380 raise
2381 except KeyError:
2382 f.close()
2383 raise KeyError("Keys in infodict not found in pointset")
2384 if isinstance(precision, int):
2385 assert precision > 0
2386 ps = str(precision)
2387 else:
2388 raise TypeError("precision must be a positive integer")
2389 if varvaldir == 'row':
2390 savetxt(f, varray, '%.'+ps+'f', separator)
2391 else:
2392 savetxt(f, transpose(varray), '%.'+ps+'f', separator)
2393 f.close()
2394
2395
2396 -def importPointset(xFileName, t=None, indices=None, sep=" ",
2397 preamblelines=0):
2398 """Import ASCII format files containing data points.
2399 If the first row contains string names then the output
2400 will be a pointset, otherwise a numeric array.
2401
2402 A dictionary is returned, with keys 'vararray' will point to the
2403 data. The 't' argument can specify one of several things:
2404
2405 string: filename to read single-column of time values (same length as
2406 xFileName)
2407 sequence type: time values (same length as xFileName)
2408 integer: column in xFileName to treat as time data
2409
2410 If used, this leads to and an additional key in the return
2411 dictionary where 't' points to the independent variable array.
2412
2413 Specific columns can be selected for the variable data array by
2414 specifying a list of column indices in argument 'indices'.
2415
2416 The separator used in the ASCII file can be specified by argument
2417 'sep' (defaults to single whitespace character).
2418
2419 preamblelines (positive integer) specifies how many lines to skip before
2420 starting to read data (in case of preceding text) -- default 0.
2421 """
2422
2423 if indices is None:
2424 indices = []
2425 xFile = open(xFileName, 'r')
2426 xFileStrList = xFile.readlines()
2427 filelen = len(xFileStrList)-preamblelines
2428 if filelen == 1 and '\r' in xFileStrList[0]:
2429
2430 xFileStrList = xFileStrList[0].split('\r')
2431 filelen = len(xFileStrList)
2432 if filelen <= 1:
2433 raise ValueError("Only 1 data point found in variables datafile")
2434 x_dummy_all = xFileStrList[preamblelines].rstrip("\n")
2435 x_dummy_vallist = filter(lambda s: s != '', x_dummy_all.split(sep))
2436 if t is None:
2437 get_t = 0
2438 elif isinstance(t, str):
2439 tFileName = t
2440 tFile = open(tFileName, 'r')
2441 tFileStrList = tFile.readlines()
2442 if len(tFileStrList)-preamblelines != filelen:
2443 raise ValueError("Length of data and time files must be equal"
2444 " -- are there any blank lines in the files?")
2445 get_t = 1
2446 elif isinstance(t, _seq_types):
2447 if len(t) != filelen:
2448 raise ValueError("Length of data file and t array must be "
2449 "equal -- are there any blank lines in the files?")
2450 tVals = t
2451 get_t = 0
2452 elif isinstance(t, _int_types):
2453
2454 if t >= len(x_dummy_vallist) or t < 0:
2455 raise ValueError("t index out of range")
2456 get_t = 2
2457 if indices == []:
2458 if get_t == 2:
2459 dim = len(x_dummy_vallist)-1
2460 indices = remain(range(0,dim+1),[t])
2461 else:
2462 dim = len(x_dummy_vallist)
2463 indices = range(0,dim)
2464 else:
2465 dim = len(indices)
2466 if get_t == 2:
2467 if t in indices:
2468 raise ValueError("You specified column "+str(t)+" as time "
2469 "data, but you have specified it as a data column in "
2470 "indices argument")
2471
2472 start = preamblelines
2473
2474 test_line = [n.strip('"').strip("'") for n in \
2475 xFileStrList[preamblelines].lstrip(sep).lstrip(" ").rstrip("\n").rstrip("\r").split(sep)]
2476 def is_float(vstr):
2477 try:
2478 val = float(vstr)
2479 except ValueError:
2480 return False
2481 else:
2482 return True
2483 if alltrue([not is_float(n) for n in test_line]):
2484
2485 start += 1
2486
2487 test_line = [n.replace(" ", "_").replace(".","") for n in test_line]
2488 if get_t == 2:
2489 t_name = test_line[t]
2490 varnames = test_line[0:t]+test_line[t+1:]
2491 else:
2492 if get_t == 1:
2493
2494 t_test = tFileStrList[0].lstrip(" ").rstrip("\n").rstrip("\r").replace(".","").replace(" ","_").strip('"').strip("'")
2495 if is_float(t_test):
2496
2497 raise ValueError("First line of t file shouldn't be a number")
2498 else:
2499 t_name = t_test
2500 else:
2501 t_name = 't'
2502 varnames = test_line
2503 else:
2504 t_name = 't'
2505 varnames = None
2506 tVals = zeros(filelen-start, float)
2507 xVals = zeros([filelen-start, dim], float)
2508
2509 for i in xrange(filelen-start):
2510 vLine = xFileStrList[i+start].rstrip("\n")
2511 if vLine == '':
2512 continue
2513 vLineVals = filter(lambda s: s != '', vLine.split(sep))
2514 if get_t == 1:
2515
2516 tLine = tFileStrList[i+start].rstrip("\n").lstrip(sep).lstrip(" ")
2517 if len(tLine.split(sep)) != 1:
2518 raise ValueError("Only one t value expected per line of"
2519 " datafile")
2520 if tLine == '':
2521 continue
2522 tVals[i] = float(tLine)
2523 elif get_t == 2:
2524 tVals[i] = float(vLineVals[t])
2525 try:
2526 xLineVals = [vLineVals[ix] for ix in indices]
2527 except IndexError:
2528 print "Valid indices were: 0 -", len(vLineVals)-1
2529 raise
2530 if len(xLineVals) != dim:
2531 raise ValueError("Exactly "+str(dim)+" values expected per "
2532 "line of datafile")
2533 xVals[i] = array([float(xstr) for xstr in xLineVals], float)
2534 xFile.close()
2535 if get_t == 1:
2536 tFile.close()
2537 if get_t == 0:
2538 if varnames is None:
2539 return xVals
2540 else:
2541
2542 return Pointset(dict(zip(varnames, xVals)))
2543 else:
2544 if varnames is None:
2545 return {t_name: tVals, 'vararray': xVals.T}
2546 else:
2547 return Pointset(indepvardict={t_name: tVals},
2548 coorddict=dict(zip(varnames,xVals.T)))
2549
2550
2552 """Simple export that ignores all metadata in pts,
2553 including name, tags, norm, etc.
2554 Data is arranged by row only.
2555
2556 Independent variable is first column, if it exists in pts.
2557 """
2558 import csv
2559 outfile = open(filename, 'w')
2560 writer = csv.writer(outfile)
2561
2562
2563 if pts._parameterized:
2564 rows_header = [pts.indepvarname] + pts.coordnames
2565 else:
2566 rows_header = pts.coordnames
2567 writer.writerow(rows_header)
2568
2569
2570 if pts._parameterized:
2571 for i in xrange(len(pts)):
2572 writer.writerow([pts.indepvararray[i]] + list(pts.coordarray[:,i]))
2573 else:
2574 for i in xrange(len(pts)):
2575 writer.writerow(pts.coordarray[:,i])
2576
2577 outfile.close()
2578
2579
2581 """Merges two pointsets into a new pointset, preserving (merging) any
2582 metadata in each.
2583
2584 In particular, if each have different accuracy tolerances, the
2585 larger of the two will be used. If each have different 'checklevel' values,
2586 the larger of the two will be used. Point labels will be merged. Names
2587 will also be merged.
2588
2589 If both are parameterized, their independent variable arrays
2590 must be identical. If only one is parameterized, the result will be
2591 too. The two pointsets must be identical in length.
2592
2593 The norm associated with each pointset must be the same.
2594 """
2595 len1 = len(pts1)
2596 len2 = len(pts2)
2597 assert len1 == len2, "Pointsets must have equal length"
2598 assert pts1._normord == pts2._normord, "Pointsets must use the same norm"
2599 isparam1 = isparameterized(pts1)
2600 isparam2 = isparameterized(pts2)
2601 if isparam1 and isparam2:
2602 assert pts1.indepvarname == pts2.indepvarname, \
2603 "Parameterized pointsets must have identical independent variable names"
2604 assert all(pts1.indepvararray == pts2.indepvararray), \
2605 "Parameterized pointsets must have identical independent variable values"
2606 common_coords = intersect(pts1.coordnames, pts2.coordnames)
2607 for c in common_coords:
2608 assert all(pts1[c] == pts2[c]), \
2609 "Pointsets must not share any coordinate names whose values are not identical"
2610 args = {}
2611 if isparam1 or isparam2:
2612 if isparam1:
2613 tvals = pts1.indepvararray
2614 tname = pts1.indepvarname
2615 else:
2616 tvals = pts2.indepvararray
2617 tname = pts2.indepvarname
2618 args['indepvardict'] = {tname: tvals}
2619 args['checklevel'] = max(pts1.checklevel, pts2.checklevel)
2620 args['tolerance'] = max(pts1._abseps, pts2._abseps)
2621 if name is None:
2622 if pts1.name == "":
2623 name1 = "<unnamed>"
2624 else:
2625 name1 = pts1.name
2626 if pts2.name == "":
2627 name2 = "<unnamed>"
2628 else:
2629 name2 = pts2.name
2630 args['name'] = "Merged %s:%s" % (name1, name2)
2631 coorddict = pts1.todict()
2632 coorddict.update(pts2.todict())
2633 args['coorddict'] = coorddict
2634 lab1 = deepcopy(pts1.labels)
2635 lab2 = deepcopy(pts2.labels)
2636 lab2.update(lab1)
2637 args['labels'] = lab2
2638 return Pointset(**args)
2639
2640
2641 -def padPointset(pts, pinterval, value_dict, eps=None):
2642 """Pad a pointset pts with values from value_dict over the interval given
2643 by pinterval (pair). For each side of the interval outside of the current independent
2644 variable domain of pts, two new points are added, one at the outer limit
2645 of the interval, and one a distance eps (default the abseps setting of pts)
2646 from the existing closest point in pts.
2647 """
2648 tlo, thi = pinterval
2649 ts = pts.indepvararray
2650 all_dict = value_dict.copy()
2651 assert remain(value_dict.keys(), pts.coordnames) == []
2652 if eps is None:
2653 eps = pts._abseps
2654 if tlo < ts[0]:
2655 all_dict['t'] = tlo
2656 pts.insert(Point(coorddict=all_dict,
2657 labels='pad'))
2658 all_dict['t'] = ts[0]-eps
2659 pts.insert(Point(coorddict=all_dict,
2660 labels='pad'))
2661 if thi > ts[-1]:
2662 all_dict['t'] = ts[-1]+eps
2663 pts.insert(Point(coorddict=all_dict,
2664 labels='pad'))
2665 all_dict['t'] = thi
2666 pts.insert(Point(coorddict=all_dict,
2667 labels='pad'))
2668 return pts
2669