OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
auxiliary.py
Go to the documentation of this file.
1 import numpy as np
2 import sys
3 import pandas as pd
4 from datetime import datetime as DT
5 
6 
7 def qtpow(q, pwr):
8  # NAME:
9  # qtpow
10  #
11  # Converted to python by R. Healy (2/9/2016) richard.healy@nasa.gov
12  #
13  # AUTHOR:
14  # Craig B. Markwardt, NASA/GSFC Code 662, Greenbelt, MD 20770
15  # craigm@lheamail.gsfc.nasa.gov
16  # UPDATED VERSIONs can be found on my WEB PAGE:
17  # http://cow.physics.wisc.edu/~craigm/idl/idl.html
18  #
19  # PURPOSE:
20  # Raise quaternion Q to the "power" POW
21  #
22  # MAJOR TOPICS:
23  # Geometry
24  #
25  # CALLING SEQUENCE:
26  # QNEW = QTPOW(Q, POW)
27  #
28  # DESCRIPTION:
29  #
30  # The function QTPOW raises a quaterion Q to the power P. The operation
31  #
32  # QNEW = QTPOW(Q, POW)
33  #
34  # is equivalent to
35  #
36  # QNEW = QTEXP( POW * QTLOG(Q))
37  #
38  # which is the same as the definition of raising a real number to
39  # any power (however, QTPOW is faster than using QTLOG and QTEXP).
40  #
41  # For integer values of POW, this form of exponentiation is also
42  # directly equivalent to the multiplication of that many Q's
43  # together.
44 
45  nq = q.size/4
46  npw = pwr.size
47  if nq < 1 or npw < 1:
48  sys.exit('qtpow: Invalid array size')
49 
50  v = q[:, 0:3]
51  sinth = np.sqrt(np.sum(np.power(v, 2), axis=1))
52  th = np.arctan2(sinth, q[:, 3])
53  rat = th*0
54  wh = (sinth != 0)
55  if wh.size > 0:
56  rat[wh] = np.sin(np.multiply(pwr[wh], th[wh]))/sinth[wh]
57  q1 = np.zeros(q.shape)
58  q1[:, 3] = np.cos(np.multiply(th, pwr))
59  q1[:, 0:3] = np.multiply(np.tile(rat, (3, 1)).T, v)
60  return q1
61 
62 
63 def qtmult(aqt, bqt, inverse1=0, inverse2=0):
64  '''This will only work with hico'''
65 
66  sz1 = aqt.shape
67  sz2 = bqt.shape
68  print('sz1,sz2=', sz1, sz2)
69  if sz1[0] < 1 or sz2[0] < 1:
70  sys.exit('ERROR A: Q1 and Q2 must be quaternions')
71  if sz1[1] != 4 or sz2[1] != 4:
72  sys.exit('ERROR B: Q1 and Q2 must be quaternions')
73 
74  n1 = aqt.size/4
75  n2 = bqt.size/4
76 
77  if n1 != n2 and n1 != 1 and n2 != 1:
78  sys.exit('ERROR: Q1 and Q2 must both have the same number of quaternions')
79 
80  # nq = np.max(n1,n2)
81  cqt = np.zeros(aqt.shape)
82  aqt0 = np.squeeze(aqt[:, 0])
83  aqt1 = np.squeeze(aqt[:, 1])
84  aqt2 = np.squeeze(aqt[:, 2])
85  aqt3 = np.squeeze(aqt[:, 3])
86 
87  bqt0 = np.squeeze(bqt[:, 0])
88  bqt1 = np.squeeze(bqt[:, 1])
89  bqt2 = np.squeeze(bqt[:, 2])
90  bqt3 = np.squeeze(bqt[:, 3])
91 
92  if inverse1 > 0:
93  aqt0 = -aqt0
94  aqt1 = -aqt1
95  aqt2 = -aqt2
96 
97  if inverse2 > 0:
98  bqt0 = -bqt0
99  bqt1 = -bqt1
100  bqt2 = -bqt2
101 # print('aqt1=',aqt1.shape,'aqt2=',aqt2.shape,'aqt3=',aqt3.shape,'aqt0=',aqt0.shape)
102 # print('bqt1=',bqt1.shape,'bqt2=',bqt2.shape,'bqt3=',bqt3.shape,'bqt0=',bqt0.shape)
103 # print('mult=',np.multiply(aqt0,bqt3).shape)
104  cqt[:, 0] = np.squeeze([np.multiply(aqt0, bqt3) + np.multiply(aqt1, bqt2) -
105  np.multiply(aqt2, bqt1) + np.multiply(aqt3, bqt0)])
106  cqt[:, 1] = np.squeeze([-np.multiply(aqt0, bqt2) + np.multiply(aqt1, bqt3) +
107  np.multiply(aqt2, bqt0) + np.multiply(aqt3, bqt1)])
108  cqt[:, 2] = np.squeeze([np.multiply(aqt0, bqt1) - np.multiply(aqt1, bqt0) +
109  np.multiply(aqt2, bqt3) + np.multiply(aqt3, bqt2)])
110  cqt[:, 3] = np.squeeze([-np.multiply(aqt0, bqt0) - np.multiply(aqt1, bqt1) -
111  np.multiply(aqt2, bqt2) + np.multiply(aqt3, bqt3)])
112  return cqt
113 
114 
115 def qterp_slerp(t0, q0, t1):
116  # NAME:
117  # QTERP
118  # Converted to python by R. Healy (richard.healy@nasa.gov) 2/10/16
119  #
120  # AUTHOR:
121  # Translated to python by Rick Healy (richard.healy@nasa.gov)
122  #
123  # Craig B. Markwardt, NASA/GSFC Code 662, Greenbelt, MD 20770
124  # craigm@lheamail.gsfc.nasa.gov
125  # UPDATED VERSIONs can be found on my WEB PAGE:
126  # http://cow.physics.wisc.edu/~craigm/idl/idl.html
127  #
128  # PURPOSE:
129  # Smoothly interpolate from a grid of quaternions (spline or slerp)
130  #
131  # MAJOR TOPICS:
132  # Geometry
133  #
134  # CALLING SEQUENCE:
135  # QNEW = QTERP(TGRID, QGRID, TNEW, [/SLERP], QDIFF=, [/RESET])
136  #
137  # DESCRIPTION:
138  #
139  # The function QTERP is used to interplate from a set of known unit
140  # quaternions specified on a grid of independent values, to a new set
141  # of independent values. For example, given a set of quaternions at
142  # specified key times, QTERP can interpolate at any points between
143  # those times. This has applications for computer animation and
144  # spacecraft attitude control.
145  #
146  nq = np.int(q0.size / 4)
147  if nq == 1:
148  return np.tile(q0.T, (t1.size, 1))
149 
150  qdiff = qtmult(q0[0:nq-1, :], q0[1:, :], inverse1=1)
151  wh = qdiff[:, 3] < 0
152  qn = qdiff[wh, 3]
153  if qn.size > 0:
154  qdiff[wh, 3] = -qdiff[wh, 3]
155  # ii = value_locate(t0, t1)
156  ii = ValueLocate(t0, t1)
157  hh = np.zeros(len(t1))
158  # Maybe there's a better way to do this, but for now this works.
159  # The way IDL does this is totally mysterious to me since it
160  # subtracts t0(ii) from t1 without reference to ii or the number of ii's
161  # and passing hh the same way
162  for i in np.arange(0, len(ii)):
163  if ii[i] > 0 and ii[i] < nq-1:
164  hh[i] = (t1[i] - t0[ii[i]]) / (t0[ii[i] + 1] - t0[ii[i]])
165  ii2 = (ii[ii > 0])
166  ii3 = (ii2[ii2 < nq-1])
167  return qtmult(q0[ii3, :], qtpow(qdiff[ii3, :], hh[ii3]))
168 
169 
170 def ValueLocate(vec, vals):
171  '''
172  Equivalent to IDL's value_locate routine. Excerpt from exelis follows
173  "The VALUE_LOCATE function finds the intervals within a given monotonic
174  vector that brackets a given set of one or more search values."
175  Assumes vec and val are 1D arrays
176  '''
177  return np.amax([np.where(v >= vec, np.arange(len(vec)), -1)
178  for v in vals], axis=1)
179 
180 
181 def ConvLst2DT(date, time):
182  """
183  Takes a date and time strings and returns a datetime object"""
184  ds = ','.join([str(int(x)) for x in date + time])
185  try:
186  return DT.strptime(ds, '%Y,%m,%d,%H,%M,%S')
187  except ValueError:
188  print('Conversion error. Check validity of date/time entries:')
189  keys = ['yr', 'mo', 'day', 'hr', 'min', 'sec']
190  for key, entry in zip(keys, ds.split(',')):
191  print('%s: %s' %(key, entry))
192 
193 
194 
195 def GetOdrcTimeOffset(refHdrFile):
196  with open(refHdrFile) as f:
197  lines = f.read()
198  fline = lines.find('odrc_time_offset')
199  if fline >= 0:
200  return float(lines[fline:].split('\n')[0].split('=')[1].strip())
201  return None
202 
203 
204 class CNamespace():
205  '''
206  Class to replace command line argument parser for IPython calls.
207  Example Usage: args=Namespace(ifile='',opath='',prsil='',prnoi='')
208  **kwargs can be anything needed
209  '''
210 
211  def __init__(self, **kwargs):
212  self.__dict__.update(kwargs)
213  return None
def GetOdrcTimeOffset(refHdrFile)
Definition: auxiliary.py:195
def qterp_slerp(t0, q0, t1)
Definition: auxiliary.py:115
def ConvLst2DT(date, time)
Definition: auxiliary.py:181
def ValueLocate(vec, vals)
Definition: auxiliary.py:170
const char * str
Definition: l1c_msi.cpp:35
def qtpow(q, pwr)
Definition: auxiliary.py:7
def qtmult(aqt, bqt, inverse1=0, inverse2=0)
Definition: auxiliary.py:63
def __init__(self, **kwargs)
Definition: auxiliary.py:211