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
colorterms.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008, 2009, 2010, 2011 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 import numpy as np
23 
24 class Colorterm(object):
25  """A class to describe colour terms between photometric bands"""
26 
27  _colorterms = {} # cached dictionary of dictionaries of Colorterms for devices
28  _activeColorterms = None # The set of Colorterms that are currently in use
29 
30  def __init__(self, primary, secondary, c0, c1=0.0, c2=0.0):
31  """The transformed magnitude p' is given by
32  p' = primary + c0 + c1*(primary - secondary) + c2*(primary - secondary)**2
33  """
34  self.primary = primary
35  self.secondary = secondary
36  self.c0 = c0
37  self.c1 = c1
38  self.c2 = c2
39 
40  def __str__(self):
41  return "%s %s [%g %g %g]" % (self.primary, self.secondary, self.c0, self.c1, self.c2)
42 
43  @staticmethod
44  def setColorterms(colorterms, device=None):
45  """Set the cached Colorterms dict for <device> to <colorterms>
46 If device is omitted, set the dictionary of known devices' Colorterms
47 """
48  if device:
49  Colorterm._colorterms[device] = colorterms[device]
50  else:
51  Colorterm._colorterms = colorterms
52 
53  Colorterm.setActiveDevice(device, allowRaise=False)
54 
55  @staticmethod
56  def setActiveDevice(device, allowRaise=True):
57  """Set the default colour terms to those appropriate for <device>"""
58  try:
59  Colorterm._activeColorterms = Colorterm._colorterms[device]
60  except KeyError:
61  if device is not None and allowRaise:
62  raise RuntimeError("No colour terms are available for %s" % device)
63 
64  Colorterm._activeColorterms = None
65 
66  @staticmethod
67  def getColorterm(band):
68  """Return the Colorterm for the specified band (or None if unknown)"""
69  return Colorterm._activeColorterms.get(band) if Colorterm._activeColorterms else None
70 
71  @staticmethod
72  def transformSource(band, source, reverse=False, colorterms=None):
73  """Transform the magnitudes in <source> to the specified <band> and return it. The <source> must
74 support a get(band) (e.g. source.get("r")) method, as do afw::Source and dicts.
75 Use the colorterms (or the cached set if colorterms is None); if no set is available, return the <band> flux
76 If reverse is True, return the inverse transformed magnitude
77  """
78  if not colorterms:
79  colorterms = Colorterm._activeColorterms
80 
81  if not colorterms:
82  return source.get(band)
83 
84  ct = colorterms[band]
85 
86  return Colorterm.transformMags(band, source.get(ct.primary), source.get(ct.secondary),
87  reverse, colorterms)
88 
89  @staticmethod
90  def transformMags(band, primary, secondary, reverse=False, colorterms=None):
91  """Transform the magnitudes <primary> and <secondary> to the specified <band> and return it.
92 Use the colorterms (or the cached set if colorterms is None); if no set is available, return the <band> flux
93 If reverse is True, return the inverse transformed magnitude
94  """
95  if not colorterms:
96  colorterms = Colorterm._activeColorterms
97 
98  if not colorterms:
99  return p
100 
101  ct = colorterms[band]
102 
103  p = primary
104  s = secondary
105 
106  if reverse:
107  raise NotImplemented("reverse photometric transformations are not implemented")
108  else:
109  return p + ct.c0 + (p - s)*(ct.c1 + (p - s)*ct.c2)
110 
111  @staticmethod
112  def propagateFluxErrors(band, primaryFluxErr, secondaryFluxErr, reverse=False, colorterms=None):
113  if not colorterms:
114  colorterms = Colorterm._activeColorterms
115 
116  if not colorterms:
117  return primaryFluxErr
118 
119  ct = colorterms[band]
120 
121  return np.hypot((1 + ct.c1)*primaryFluxErr, ct.c1*secondaryFluxErr)
122