OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
GEO_derived_products.c
Go to the documentation of this file.
1 #include "PGS_CBP.h"
2 #include "PGS_MODIS_35251.h"
3 #include "GEO_output.h"
4 #include "GEO_global_arrays.h"
5 #include "GEO_util.h"
6 #include "GEO_geo.h"
7 
8 PGSt_SMF_status GEO_derived_products(
9  int const num_frames,
10  int const num_detectors,
11  double ecr_sample_position[][MAX_SCAN_SAMPLE][3],
12  double ecr_sc_position[][3],
13  unsigned char pixel_flags[][MAX_SCAN_SAMPLE],
14  double terrain_sample_position[][MAX_SCAN_SAMPLE][3],
15  char utc[],
16  PGSt_double toff[],
17  double sample_solar_angles[][MAX_SCAN_SAMPLE][2],
18  double sample_to_sensor[][MAX_SCAN_SAMPLE][3]
19 )
20 /*
21 !C*****************************************************************************
22 !Description:
23  Subroutine in output group of the Level-1A geolocation software to
24  compute the derived products, consisting of the sensor azimuth and
25  zenith angles, the pixel-to-sensor range, and the solar azimuth and
26  zenith angles.
27 
28 !Input Parameters:
29  num_frames The number of frames to process
30  num_detectors The number of detectors in the sample
31  ecr_sample_position The ellipsoid intersection points in ECR
32  coordinates.
33  ecr_sc_position The spacecraft positions in ECR coordinates.
34  terrain_sample_position Terrain_corrected ground positions
35  utc The time of the start of a scan, as a character
36  string in UTC format.
37  toff Offsets from 'utc'
38 
39 !Output Parameters:
40  sample_solar_angles Solar azimuth and zenith angles
41  sample_to_sensor Sensor azimuth and zenith angles and range
42 
43 !Input/Output Parameters:
44  pixel_flags Pixel flags.
45 
46 Return value:
47  MODIS_E_GEO If any subroutine fails.
48  MODIS_E_BAD_INPUT_ARG Invalid input argument
49  PGS_S_SUCCESS Otherwise
50 
51 Externally Defined:
52  azimuth_index "GEO_global_arrays.h"
53  MAX_DETECTORS "GEO_geo.h"
54  MAX_SCAN_SAMPLE "GEO_geo.h"
55  MODIS_E_BAD_INPUT_ARG "PGS_MODIS_35251.h"
56  MODIS_E_GEO "PGS_MODIS_35251.h"
57  NO_ELLIPSE_INTERSECT "GEO_geo.h"
58  PGS_S_SUCCESS "PGS_SMF.h"
59  PGSCBP_W_BAD_CB_VECTOR "PGS_CBP_6.h"
60  PGSCSC_W_PREDICTED_UT1 "PGS_CSC.h"
61  range_index "GEO_global_arrays.h"
62  SENSORAZIM_FVALUE "GEO_geo.h"
63  SENSORZEN_FVALUE "GEO_geo.h"
64  SOLARAZIM_FVALUE "GEO_geo.h"
65  SOLARZEN_FVALUE "GEO_geo.h"
66  z_angle_index "GEO_global_arrays.h"
67 
68 Called by:
69  GEO_locate_one_scan
70 
71 Routines Called:
72  GEO_vec_mul3 "GEO_utils.h"
73  GEO_vec_length3 "GEO_utils.h"
74  GEO_vec_prod3 "GEO_utils.h"
75  modsmf "smfio.h"
76  PGS_CBP_Earth_CB_Vector "PGS_CBP.h"
77  PGS_CSC_ECItoECR "PGS_CSC.h"
78 
79 !Revision History:
80  $Log: GEO_derived_products.c,v $
81  Revision 6.2 2010/06/29 18:44:37 kuyper
82  Replaced equality test involving floating point numbers with an inequality.
83 
84  Revision 6.1 2010/06/18 20:08:07 kuyper
85  Removed const qualifiers from pointer to array arguments.
86 
87  Revision 4.5 2003/10/27 01:01:57 vlin
88  expanded message buffer size
89 
90  Revision 4.4 2003/09/24 18:46:49 vlin
91  Added some lines to check input arguments
92 
93  Revision 4.3 2003/08/26 21:06:25 kuyper
94  Corrected obsolete setting of toff.
95 
96  Revision 4.2 2003/08/18 20:33:52 kuyper
97  Move two globals to GEO_locate_one_scan.c.
98 
99  Revision 4.1 2003/08/12 16:09:40 vlin
100  Changed to use parameters rather than global variables,
101  process entire scan in one call, and allowing greater efficiency
102  in the SDP Toolkit function calls.
103 
104  Revision 1.11 1997/10/22 20:21:50 jjb
105  Added initialization of (global) outputs.
106 
107  10/3/95
108  Frederick S. Patt
109  Revised calculation of range to account for terrain correction
110 
111 !Team-unique Header:
112 
113  This software is developed by the MODIS Science Data Support
114  Team for the National Aeronautics and Space Administration,
115  Goddard Space Flight Center, under contract NAS5-32373.
116 
117 !END
118 ******************************************************************************/
119 
120 {
121  int sample_number, idet = 0, j = 0;
122  double clon = 0.0; /* cosine of longitude */
123  double clat = 0.0; /* cosine of latitude */
124  double slon = 0.0; /* sine of longitude */
125  double slat = 0.0; /* sine of latitude */
126  double n[3] = {0.0}; /* normal vector */
127  double e[3] = {0.0}; /* East vector */
128  double a[3] = {0.0}; /* vector perpendicular to n and e */
129  double v[3] = {0.0}; /* pixel-to-sensor vector */
130  double vdotn = 0.0; /* Dot product of vector with n */
131  double vdote = 0.0; /* Dot product of vector with e */
132  double vdota = 0.0; /* Dot product of vector with a */
133  double sunecr[3] = {0.0}; /* Sun vector in ECR frame */
134  PGSt_double sun[MAX_SCAN_SAMPLE][3] = {0.0}; /* Sun vector in ECI frame */
135  PGSt_double tveci[MAX_SCAN_SAMPLE][6] = {0.0};
136  PGSt_double tvecr[MAX_SCAN_SAMPLE][6] = {0.0};
137  PGSt_SMF_status PGS_error_code;
138  char msgbuf[256] = "";
139  char filefunc[] = __FILE__ ", GEO_derived_products";
140 
141  if (num_frames < 0 || num_frames > MAX_SCAN_SAMPLE ||
142  num_detectors < 0 || num_detectors > MAX_DETECTORS ||
143  utc == NULL || toff == NULL) {
144  sprintf(msgbuf, "num_frames: %d, num_detectors: %d,\nutc: %s, toff:%p",
145  num_frames, num_detectors, utc, (void *)toff);
146  modsmf(MODIS_E_BAD_INPUT_ARG, msgbuf, filefunc);
147  return MODIS_E_BAD_INPUT_ARG;
148  }
149 
150  if (ecr_sample_position == NULL || ecr_sc_position == NULL ||
151  pixel_flags == NULL || terrain_sample_position == NULL ||
152  sample_solar_angles == NULL || sample_to_sensor == NULL) {
153  sprintf(msgbuf, "ecr_sample_position: %p, ecr_sc_position:%p, \n "
154  "pixel_flags: %p, terrain_sample_position: %p, \n"
155  "sample_solar_angles: %p, sample_to_sensor: %p",
156  (void *)ecr_sample_position,(void *)ecr_sc_position,(void *)pixel_flags,
157  (void *)terrain_sample_position,(void *)sample_solar_angles,
158  (void *)sample_to_sensor);
159  modsmf(MODIS_E_BAD_INPUT_ARG, msgbuf, filefunc);
160  return MODIS_E_BAD_INPUT_ARG;
161  }
162 
163  for (idet = 0; idet < num_detectors; idet++) {
164  for (sample_number = 0; sample_number < num_frames; sample_number++) {
165  sample_to_sensor[idet][sample_number][z_angle_index] =
167  sample_to_sensor[idet][sample_number][azimuth_index] =
169  sample_to_sensor[idet][sample_number][range_index] = (double) RANGE_FVALUE;
170  sample_solar_angles[idet][sample_number][z_angle_index] =
172  sample_solar_angles[idet][sample_number][azimuth_index] =
174  }
175  }
176 
177  /* Get Sun vector */
178  PGS_error_code = PGS_CBP_Earth_CB_Vector(num_frames,utc,toff,PGSd_SUN,sun);
179  if (PGS_error_code != PGS_S_SUCCESS &&
180  PGS_error_code != PGSCBP_W_BAD_CB_VECTOR) {
181  sprintf(msgbuf,"PGS_CBP_Earth_CB_Vector(%s)", utc);
182  modsmf(MODIS_E_GEO, msgbuf, filefunc);
183  return MODIS_E_GEO;
184  }
185 
186  for (sample_number = 0; sample_number < num_frames; sample_number++)
187  for (j=0; j<3; j++)
188  tveci[sample_number][j] = sun[sample_number][j];
189 
190  PGS_error_code = PGS_CSC_ECItoECR(num_frames,utc,toff,tveci,tvecr);
191  if (PGS_error_code != PGS_S_SUCCESS &&
192  PGS_error_code != PGSCSC_W_PREDICTED_UT1) {
193  sprintf(msgbuf,"PGS_CSC_ECItoECR(%s)", utc);
194  modsmf(MODIS_E_GEO, msgbuf, filefunc);
195  return MODIS_E_GEO;
196  }
197 
198  for (sample_number = 0; sample_number < num_frames; sample_number++) {
199  for (j=0; j<3; j++)
200  sunecr[j] = (double)tvecr[sample_number][j];
201 
202  for (idet = 0; idet < num_detectors; idet++) {
203  if (pixel_flags[idet][sample_number] < NO_ELLIPSE_INTERSECT) {
204  /* Compute the normal and East vectors */
205  clon = cos(terrain_sample_position[idet][sample_number][1]);
206  clat = cos(terrain_sample_position[idet][sample_number][0]);
207  slon = sin(terrain_sample_position[idet][sample_number][1]);
208  slat = sin(terrain_sample_position[idet][sample_number][0]);
209  n[0] = clat*clon;
210  n[1] = clat*slon;
211  n[2] = slat;
212  e[0] = -slon;
213  e[1] = clon;
214 
215  /* Compute the perpendicular vector */
216  GEO_vec_mul3(n, e, a);
217 
218  /* Compute the sample-to-sensor vector and store in v */
219  for (j = 0; j < 3; j++)
220  v[j] = ecr_sc_position[sample_number][j]
221  - ecr_sample_position[idet][sample_number][j];
222 
223  /* Compute the sensor azimuth and zenith angles and range */
224  GEO_vec_prod3(v, n, &vdotn);
225  GEO_vec_prod3(v, e, &vdote);
226  GEO_vec_prod3(v, a, &vdota);
227  sample_to_sensor[idet][sample_number][z_angle_index] =
228  atan2(sqrt(vdote*vdote + vdota*vdota),vdotn);
229  sample_to_sensor[idet][sample_number][azimuth_index] = atan2(vdote,vdota);
230  GEO_vec_length3(v,&sample_to_sensor[idet][sample_number][range_index]);
231 
232  if (sunecr[0] >= PGSd_GEO_ERROR_VALUE)
233  pixel_flags[idet][sample_number] |= INVALID_SOLAR_ANGLES;
234  else {
235  GEO_vec_prod3(sunecr, n, &vdotn);
236  GEO_vec_prod3(sunecr, e, &vdote);
237  GEO_vec_prod3(sunecr, a, &vdota);
238  sample_solar_angles[idet][sample_number][1] =
239  atan2(sqrt(vdote*vdote + vdota*vdota),vdotn);
240  sample_solar_angles[idet][sample_number][0] = atan2(vdote,vdota);
241  }
242  }
243  } /* End of detector loop */
244  }
245  return PGS_S_SUCCESS;
246 }
#define SOLARZEN_FVALUE
Definition: GEO_geo.h:152
int j
Definition: decode_rs.h:73
#define SENSORAZIM_FVALUE
Definition: GEO_geo.h:150
#define NULL
Definition: decode_rs.h:63
#define MODIS_E_BAD_INPUT_ARG
const unsigned char NO_ELLIPSE_INTERSECT
const int MAX_SCAN_SAMPLE
#define SENSORZEN_FVALUE
Definition: GEO_geo.h:149
@ azimuth_index
#define MODIS_E_GEO
const int MAX_DETECTORS
void GEO_vec_prod3(double vec1[3], double vec2[3], double *const prod)
Definition: GEO_vec_prod3.c:6
integer, parameter double
int GEO_vec_mul3(double vec1[3], double vec2[3], double vec[3])
Definition: GEO_vec_mul3.c:6
@ range_index
PGSt_SMF_status GEO_derived_products(int const num_frames, int const num_detectors, double ecr_sample_position[][MAX_SCAN_SAMPLE][3], double ecr_sc_position[][3], unsigned char pixel_flags[][MAX_SCAN_SAMPLE], double terrain_sample_position[][MAX_SCAN_SAMPLE][3], char utc[], PGSt_double toff[], double sample_solar_angles[][MAX_SCAN_SAMPLE][2], double sample_to_sensor[][MAX_SCAN_SAMPLE][3])
#define INVALID_SOLAR_ANGLES
Definition: GEO_geo.h:123
void GEO_vec_length3(double vec[3], double *const length)
@ z_angle_index
PGE01 indicating that PGE02 PGE01 V6 for and PGE01 V2 for MOD03 were used to produce the granule By convention adopted in all MODIS Terra PGE02 code versions are The fourth digit of the PGE02 version denotes the LUT version used to produce the granule The source of the metadata environment variable ProcessingCenter was changed from a QA LUT value to the Process Configuration A sign used in error in the second order term was changed to a
Definition: HISTORY.txt:424
#define SOLARAZIM_FVALUE
Definition: GEO_geo.h:153
#define RANGE_FVALUE
Definition: GEO_geo.h:151