LSSTApplications  8.0.0.0+107,8.0.0.1+13,9.1+18,9.2,master-g084aeec0a4,master-g0aced2eed8+6,master-g15627eb03c,master-g28afc54ef9,master-g3391ba5ea0,master-g3d0fb8ae5f,master-g4432ae2e89+36,master-g5c3c32f3ec+17,master-g60f1e072bb+1,master-g6a3ac32d1b,master-g76a88a4307+1,master-g7bce1f4e06+57,master-g8ff4092549+31,master-g98e65bf68e,master-ga6b77976b1+53,master-gae20e2b580+3,master-gb584cd3397+53,master-gc5448b162b+1,master-gc54cf9771d,master-gc69578ece6+1,master-gcbf758c456+22,master-gcec1da163f+63,master-gcf15f11bcc,master-gd167108223,master-gf44c96c709
LSSTDataManagementBasePackage
_syntax.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008, 2009, 2010, 2011, 2012 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 """
23 Special Python syntactic sugar for Catalogs and Records.
24 
25 This module is imported by tableLib.py, and should not need to be imported by any other module.
26 I've moved the code out of the .i file here to avoid recompiling when only pure-Python code is
27 changed.
28 """
29 
30 import fnmatch
31 import re
32 import numpy
33 import collections
34 
36  """a tuple of Key subfield extraction indices (the lower-triangular elements)."""
37  r = []
38  for i in range(self.getSize()):
39  for j in range(i+1):
40  r.append((i,j))
41  return tuple(r)
42 
44  """a tuple of subelement Keys (the lower-triangular elements)."""
45  r = []
46  for i in range(self.getSize()):
47  for j in range(i+1):
48  r.append(self[i,j])
49  return tuple(r)
50 
51 def Schema_extract(self, *patterns, **kwds):
52  """
53  Extract a dictionary of {<name>: <schema-item>} in which the field names
54  match the given shell-style glob pattern(s).
55 
56  Any number of glob patterns may be passed; the result will be the union of all
57  the result of each glob considered separately.
58 
59  Additional optional arguments may be passed as keywords:
60 
61  regex ------ A regular expression to be used in addition to any glob patterns passed
62  as positional arguments. Note that this will be compared with re.match,
63  not re.search.
64 
65  sub -------- A replacement string template (see re.MatchObject.expand) used to set the
66  dictionary keys of any fields matched by regex. The field name in the
67  SchemaItem is not modified.
68 
69  ordered----- If True, a collections.OrderedDict will be returned instead of a standard
70  dict, with the order corresponding to the definition order of the Schema.
71 
72  """
73  if kwds.pop("ordered", False):
74  d = collections.OrderedDict()
75  else:
76  d = dict()
77  regex = kwds.pop("regex", None)
78  sub = kwds.pop("sub", None)
79  if sub is not None and regex is None:
80  raise ValueError("'sub' keyword argument to extract is invalid without 'regex' argument")
81  if kwds:
82  raise ValueError("Unrecognized keyword arguments for extract: %s" % ", ".join(kwds.keys()))
83  for item in self:
84  name = item.field.getName()
85  if regex is not None:
86  m = re.match(regex, name)
87  if m is not None:
88  if sub is not None:
89  name = m.expand(sub)
90  d[name] = item
91  continue # continue outer loop so we don't match the same name twice
92  for pattern in patterns:
93  if fnmatch.fnmatchcase(item.field.getName(), pattern):
94  d[name] = item
95  break # break inner loop so we don't match the same name twice
96  return d
97 
98 def BaseRecord_extract(self, *patterns, **kwds):
99  """
100  Extract a dictionary of {<name>: <field-value>} in which the field names
101  match the given shell-style glob pattern(s).
102 
103  Any number of glob patterns may be passed; the result will be the union of all
104  the result of each glob considered separately.
105 
106  Additional optional arguments may be passed as keywords:
107 
108  items ------ The result of a call to self.schema.extract(); this will be used instead
109  of doing any new matching, and allows the pattern matching to be reused
110  to extract values from multiple records. This keyword is incompatible
111  with any position arguments and the regex, sub, and ordered keyword
112  arguments.
113 
114  split ------ If True, fields with named subfields (e.g. points) will be split into
115  separate items in the dict; instead of {"point": lsst.afw.geom.Point2I(2,3)},
116  for instance, you'd get {"point.x": 2, "point.y": 3}.
117  Default is False.
118 
119  regex ------ A regular expression to be used in addition to any glob patterns passed
120  as positional arguments. Note that this will be compared with re.match,
121  not re.search.
122 
123  sub -------- A replacement string (see re.MatchObject.expand) used to set the
124  dictionary keys of any fields matched by regex.
125 
126  ordered----- If True, a collections.OrderedDict will be returned instead of a standard
127  dict, with the order corresponding to the definition order of the Schema.
128  Default is False.
129 
130  """
131  d = kwds.pop("items", None)
132  split = kwds.pop("split", False)
133  if d is None:
134  d = self.schema.extract(*patterns, **kwds).copy()
135  elif kwds:
136  raise ValueError("Unrecognized keyword arguments for extract: %s" % ", ".join(kwds.keys()))
137  for name, schemaItem in d.items(): # can't use iteritems because we might be adding/deleting elements
138  key = schemaItem.key
139  if split and key.HAS_NAMED_SUBFIELDS:
140  for subname, subkey in zip(key.subfields, key.subkeys):
141  d["%s.%s" % (name, subname)] = self.get(subkey)
142  del d[name]
143  else:
144  d[name] = self.get(schemaItem.key)
145  return d
146 
147 def BaseColumnView_extract(self, *patterns, **kwds):
148  """
149  Extract a dictionary of {<name>: <column-array>} in which the field names
150  match the given shell-style glob pattern(s).
151 
152  Any number of glob patterns may be passed; the result will be the union of all
153  the result of each glob considered separately.
154 
155  Note that extract("*", copy=True) provides an easy way to transform a row-major
156  ColumnView into a possibly more efficient set of contiguous NumPy arrays.
157 
158  This routines unpacks Flag columns into full boolean arrays and covariances into dense
159  (i.e. non-triangular packed) arrays with dimension (N,M,M), where N is the number of
160  records and M is the dimension of the covariance matrix. Fields with named subfields
161  (e.g. points) are always split into separate dictionary items, as is done in
162  BaseRecord.extract(..., split=True). String fields are silently ignored.
163 
164  Additional optional arguments may be passed as keywords:
165 
166  items ------ The result of a call to self.schema.extract(); this will be used instead
167  of doing any new matching, and allows the pattern matching to be reused
168  to extract values from multiple records. This keyword is incompatible
169  with any position arguments and the regex, sub, and ordered keyword
170  arguments.
171 
172  where ------ Any expression that can be passed as indices to a NumPy array, including
173  slices, boolean arrays, and index arrays, that will be used to index
174  each column array. This is applied before arrays are copied when
175  copy is True, so if the indexing results in an implicit copy no
176  unnecessary second copy is performed.
177 
178  copy ------- If True, the returned arrays will be contiguous copies rather than strided
179  views into the catalog. This ensures that the lifetime of the catalog is
180  not tied to the lifetime of a particular catalog, and it also may improve
181  the performance if the array is used repeatedly.
182  Default is False.
183 
184  regex ------ A regular expression to be used in addition to any glob patterns passed
185  as positional arguments. Note that this will be compared with re.match,
186  not re.search.
187 
188  sub -------- A replacement string (see re.MatchObject.expand) used to set the
189  dictionary keys of any fields matched by regex.
190 
191  ordered----- If True, a collections.OrderedDict will be returned instead of a standard
192  dict, with the order corresponding to the definition order of the Schema.
193  Default is False.
194 
195  """
196  copy = kwds.pop("copy", False)
197  where = kwds.pop("where", None)
198  d = kwds.pop("items", None)
199  if d is None:
200  d = self.schema.extract(*patterns, **kwds).copy()
201  elif kwds:
202  raise ValueError("Unrecognized keyword arguments for extract: %s" % ", ".join(kwds.keys()))
203  def processArray(a):
204  if where is not None:
205  a = a[where]
206  if copy:
207  a = numpy.ascontiguousarray(a)
208  return a
209  for name, schemaItem in d.items(): # can't use iteritems because we might be adding/deleting elements
210  key = schemaItem.key
211  if key.HAS_NAMED_SUBFIELDS:
212  for subname, subkey in zip(key.subfields, key.subkeys):
213  d["%s.%s" % (name, subname)] = processArray(self.get(subkey))
214  del d[name]
215  elif key.getTypeString().startswith("Cov"):
216  unpacked = None
217  for idx, subkey in zip(key.subfields, key.subkeys):
218  i, j = idx
219  array = processArray(self.get(subkey))
220  if unpacked is None:
221  unpacked = numpy.zeros((array.size, key.getSize(), key.getSize()), dtype=array.dtype)
222  unpacked[:,i,j] = array
223  if i != j:
224  unpacked[:,j,i] = array
225  d[name] = unpacked
226  elif key.getTypeString() == "String":
227  del d[name]
228  else:
229  d[name] = processArray(self.get(schemaItem.key))
230  return d
SelectEigenView< T >::Type copy(Eigen::EigenBase< T > const &other)
Copy an arbitrary Eigen expression into a new EigenView.
Definition: eigen.h:390