OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
proctim2.f
Go to the documentation of this file.
1  subroutine proctim2(input,nframes,navqc,time,timref,
2  1 nlines,iret)
3 c
4 c proctim2(input,nframes,navqc,time,timref,nlines,iret)
5 c
6 c Purpose: process SeaStar time tag data into times for every scan line
7 c
8 c Calling Arguments:
9 c
10 c Name Type I/O Description
11 c -------- ---- --- -----------
12 c input struct I input data structure containing
13 c SeaStar ID and time tag
14 c nframes I*4 I number of lines of time data
15 c navqc struct I navigation quality control info
16 c time R*8 O array of time in seconds relative to
17 c timref for every scan line
18 c timref R*8 O size 3 reference time at start line
19 c of data: year, day, sec
20 c nlines I*4 O number of scan lines covered
21 c iret I*4 O return code, 0 - good
22 c
23 c By: W. Robinson, GSC, 18 Mar 93
24 c
25 c Notes:
26 c
27 c Modification History:
28 c
29 c 10 August 1993 - Modified by Frederick S. Patt, GSC to process input
30 c SeaStar time tags
31 c
32 c Commented out redundant call to fndflg. F.S. Patt, GSC, August 15, 1996.
33 c
34 c Added time offset of 4 LAC lines to time tags (to remove navigation
35 c residuals) and removed check for consecutive scan times (does not work
36 c unless scans are filled and is otherwise not needed).
37 c F.S. Patt, SAIC GSC, February 24, 1998.
38 c
39 c Modified time offset to be 6 LAC lines (1 second).
40 c F.S. Patt, SAIC GSC, January 19, 1999.
41 c
42 c Moved addition of time offset to end of routine (added to timref(3))
43 c to fix occasional problem with flagged frames at the end of the day.
44 c F.S. Patt, SAIC GSC, May 31, 2001.
45 c
46 c Fixed bug in logic which determined if first unflagged time is after
47 c a day crossing (changed .gt. to .ge.). F.S. Patt, SAIC GSC, May 31, 2001.
48 c
49 c Added capability to apply fixed time shifts for specified periods to
50 c correct extended spacecraft time error periods.
51 c F.S. Patt, SAIC, October 1, 2002.
52 
53  implicit none
54 #include "nav_cnst.fin"
55 #include "input_s.fin"
56 #include "timtag_s.fin"
57 #include "navqc_s.fin"
58  type(input_struct) :: input(maxlin)
59  type(timtag_struct) :: timtag(maxlin)
60  type(navqc_struct) :: navqc
61 c
62  integer*4 gaclac, ntim, itim, iret
63  real*8 time(maxlin), timref(3)
64  real*8 secinday
65 c
66  integer*4 nframes, flag(maxlin), flagsec(maxlin), daycross
67  integer*4 i1, i2, crosspt, nper, ilin, nlines, jd
68  integer*4 iy1, iy2, id1, id2
69  logical found, endsec
70  real*8 delsec, tolmult, delfac
71  real*8 r8sec, r8dels
72 
73  parameter(secinday = 60.d0 * 60.d0 * 24.d0 )
74  parameter(delsec = 1.d0 / 6.d0)
75  parameter(delfac = 6.d0)
76 c
77 c
78 c initialize flag arrays for seconds and for day/year
79 c
80 
81  if (input(1)%sc_id(2).eq.15) then
82  gaclac = 1
83  else
84  gaclac = 0
85  end if
86 
87  ntim = nframes
88  iret = 0
89  nper = 1
90  tolmult = 1.
91  if( gaclac .eq. 1 ) then
92  nper = 5 ! # actual lines per tlm line
93  tolmult = 4.d0 ! second tolerence multiplier
94  end if
95 c
96  do itim = 1, ntim
97  flag(itim) = 1
98  flagsec(itim) = 1
99  timtag(itim)%sec = input(itim)%msec/1.d3
100  end do
101  nlines = ntim * nper
102 c
103 c flag second, day or year values outside tolerence
104 c
105  do itim = 1, ntim
106  if( ( input(itim)%iyear .ge. navqc%yearmin ) .and.
107  1 ( input(itim)%iyear .le. navqc%yearmax ) .and.
108  1 ( input(itim)%iday .ge. 1 ) .and.
109  1 ( input(itim)%iday .le. 366 ) ) flag(itim) = 0
110 c
111  if( ( timtag(itim)%sec .ge. 0 ) .and.
112  1 ( timtag(itim)%sec .le. secinday ) ) flagsec(itim) = 0
113  end do
114 c
115 c check the consistency of the second values
116 c
117  daycross = 0 ! day crossing flag
118  crosspt = 0 ! index of crossing point
119  i2 = 0 ! i1, i2 are pointers to consecutive good sec values
120  endsec = .false. ! true if the last unflagged sec was found
121  found = .false. ! to signal that a consistent pair was found
122 c
123 c start out by finding the next unflagged second value
124 c
125  call fndflg(flagsec, ntim, 1, i1 )
126  if( i1 .le. 0 ) then
127 c
128 c no unflagged values found at all, return with error
129 c
130  iret = -1
131  write( 6, 100 )
132  100 format(' PROCTIM: no unflagged tag second values found')
133  go to 990
134  end if
135 c
136 c place the next unflagged second location in i2 and compare values
137 c
138  do while( .not. endsec )
139  call fndflg(flagsec, ntim, (i1 + 1), i2 )
140  if( i2 .le. 0 ) then
141  endsec = .true.
142  else
143  found = .true.
144 c
145 c adjust the second value past any day crossing detected
146  if( daycross .ne. 0 )
147  1 timtag(i2)%sec = timtag(i2)%sec + secinday
148 c
149 c in this success case, the day boundary was crossed
150  iy1 = input(i1)%iyear
151  id1 = input(i1)%iday
152  iy2 = input(i2)%iyear
153  id2 = input(i2)%iday
154  if ( (jd(iy2,0,id2) - jd(iy1,0,id1)) .eq. 1) then
155  daycross = 1
156  crosspt = i2
157  timtag(i2)%sec = timtag(i2)%sec + secinday
158 c end if
159  end if
160 c
161 c for next pair, move secind pointer to the first
162  i1 = i2
163  end if
164  end do
165 c
166 c make sure a consistent second pair was found
167 c
168  if( .not. found ) then
169  iret = -1
170  write( 6, 500 )
171  500 format(' PROCTIM: no consistent pairs of tag seconds were
172  1 found')
173  go to 990
174  end if
175 c
176 c interpolate the second values to the output time array
177 c
178 c first, move the second values from the timetag array to
179 c the output array
180 c
181  do ilin = 1,ntim
182  time( ( ilin - 1 ) * nper + 1 ) = timtag( ilin )%sec
183  end do
184 c
185 c extrapolate any lines required at the start of the segment
186 c
187 c use first 2 good times to extrapolate or interpolate below
188 c
189  call fndflg(flagsec, ntim, 1, i1 )
190 c
191  if( flagsec(1) .eq. 1) then
192 c
193  do ilin = 1, (i1 - 1) * nper
194  time( ilin ) = timtag(i1)%sec - delsec * tolmult *
195  1 ( (i1 - 1) * nper + 1 - ilin )
196  end do
197  end if
198 c
199 c interpolate through the available times, start with first 2 times
200 c found above
201 c
202  endsec = .false.
203  do while( .not. endsec )
204  call fndflg(flagsec, ntim, (i1 + 1), i2 )
205  if( i2 .le. 0 ) then
206  endsec = .true.
207  else
208  if( ( i2 * nper - i1 * nper ) .gt. 1 ) then
209 c there are spaces to fill in output time array
210  do ilin = (i1 - 1) * nper + 2, (i2 - 1) * nper
211  time(ilin) = timtag(i1)%sec + delsec * tolmult *
212  1 ( ilin - ( i1 - 1 ) * nper - 1 )
213  end do
214  end if
215 c
216 c find next pair to interpolate
217  i1 = i2
218  end if
219  end do
220 c
221 c extrapolate times to the end of the segment
222 c
223  if( ( flagsec(ntim) .eq. 1 ) .or. ( gaclac .eq. 1 ) ) then
224  do ilin = (i1 - 1 ) * nper + 2, ntim * nper
225  time(ilin) = timtag(i1)%sec + delsec * tolmult *
226  1 ( ilin - ( i1 - 1 ) * nper - 1 )
227  end do
228  end if
229 c
230 c locate consistent day and year with a good seconds value for
231 c the first value in a pair
232 c
233  call fndflg(flag, ntim, 1, i1 )
234  if( i1 .le. 0 ) then
235  iret = -1
236  write( 6, 300 )
237  300 format(' PROCTIM: no unflagged tag year/day values found')
238  go to 990
239  end if
240 c
241  found = .false.
242 c
243  do while( .not. found )
244  call fndflg(flag, ntim, (i1 + 1), i2)
245  if( i2 .le. 0 ) then
246  write( 6, 400 )
247  400 format(' PROCTIM: unable to find a good year/ day sequence ',
248  1 'in the segment')
249  go to 990
250  else
251  if( ( input(i1)%iyear .ne. input(i2)%iyear ) .or.
252  1 ( input(i1)%iday .ne. input(i2)%iday ) .or.
253  1 ( flagsec(i1) .eq. 1 ) ) then
254 c
255 c a start was not found, set the next pair and search again
256  i1 = i2
257  else
258  found = .true.
259  end if
260  end if
261  end do
262 c
263 c adjust the year, day for any day boundary crossings
264 c by subtracting 1 day from the date
265 c
266  r8sec = 0.
267  r8dels = 0.
268  iy1 = input(i1)%iyear
269  id1 = input(i1)%iday
270 c
271  if( ( crosspt .gt. 0 ) .and. ( i1 .ge. crosspt ) )
272  1 call ydsadd( iy1, id1, r8sec, -1, r8dels )
273 c
274  timref(1) = iy1
275  timref(2) = id1
276 c
277 c reconcile the times to start at the reference time
278 c
279  timref(3) = time(1)
280  nlines = ntim * nper
281  do ilin = 1, nlines
282  time(ilin) = time(ilin) - timref(3)
283  end do
284 
285 c add timetag offset to start time
286  timref(3) = timref(3) + delfac*delsec
287 c
288 c check for time shift period
289  call checkshift (timref)
290 
291 c and end
292 c
293  990 continue
294  return
295  end
296 
297  subroutine checkshift (timref)
298 c
299 c checkshift(timref)
300 c
301 c Purpose: apply large time shifts for specified periods
302 c
303 c Calling Arguments:
304 c
305 c Name Type I/O Description
306 c -------- ---- --- -----------
307 c timref R*4 I/O size 3 reference time at start line
308 c of data: year, day, sec
309 c
310 c By: F.S. Patt, SAIC, 1 October 2002
311 c
312 c Notes:
313 c
314 c Modification History:
315 c
316 c Added period in 2006 to correct time shift during GPS outage.
317 c F.S. Patt, 17 April 2006
318 c
319 c Added special case for 2010 with linear shift from days 57 to 88
320 c F.S. Patt, 5 April 2010
321 
322  implicit none
323 
324  real*8 timref(3)
325  real*8 r8jd, secinday
326  integer*4 i, iy, id, jd, nshift
327 
328  parameter(secinday = 60.d0 * 60.d0 * 24.d0 )
329  parameter(nshift = 5)
330 
331  real*8 sjd1(nshift), sjd2(nshift), shft(nshift)
332 
333 c Defined time shift periods and shifts
334 c Start date/time
335  data sjd1/2450995.700d0, ! Day 181, 1998, 1648 UT
336  * 2452544.625d0, ! Day 269, 2002, 1500 UT
337  * 2453807.74375d0, ! Day 71, 2006, 1751 UT
338  * 2453985.850d0, ! Day 249, 2006, 20:24 UT
339  * 2455255.d0/ ! Day 57, 2010, 12:00 UT
340 c End date/time
341  data sjd2/2450996.650d0, ! Day 182, 1998, 1536 UT
342  * 2452546.125d0, ! Day 271, 2002, 0300 UT
343  * 2453809.075d0, ! Day 73, 2006, 0148 UT
344  * 2453986.200d0, ! Day 250, 2006, 0448 UT
345  * 2455285.8d0/ ! Day 88, 2010, 19:12 UT
346 c Shift in seconds
347  data shft/8.d0,8.d0,-2.d0,-3.d0, 0.d0/
348 
349 c Convert reference time to Julian day
350  iy = timref(1)
351  id = timref(2)
352  r8jd = jd(iy, 1, id) + timref(3)/secinday
353 
354 c Compute 2010 shift period as linear function of time
355  shft(5) = (r8jd - sjd1(5))*0.41d0
356 
357 c Check against defined shift periods
358  do i = 1,nshift
359 
360 c If reference time is within shift time range, apply shift
361  if ((r8jd.gt.sjd1(i)).and.(r8jd.lt.sjd2(i))) then
362  timref(3) = timref(3) + shft(i)
363  write(*,*) 'Time shift applied ', shft(i)
364  end if
365  end do
366 
367  return
368  end
#define real
Definition: DbAlgOcean.cpp:26
subroutine ydsadd(iy, id, sec, deld, delsec)
Definition: ydsadd.f:2
subroutine fndflg(flag, nflag, istndx, next)
Definition: fndflg.f:2
README for MOD_PR03(V6.1.0) 2. POINTS OF CONTACT it can be either SDP Toolkit or MODIS Packet for Terra input files The orbit validation configuration parameter(LUN 600281) must be either "TRUE" or "FALSE". It needs to be "FALSE" when running in Near Real Time mode
subroutine checkshift(timref)
Definition: proctim2.f:298
subroutine proctim2(input, nframes, navqc, time, timref, nlines, iret)
Definition: proctim2.f:3
Definition: jd.py:1