XTime.cc
1 |
//----------------------------------------------------------------------
|
---|---|
2 |
//
|
3 |
//
|
4 |
// File: XTime.C
|
5 |
// Programmer: Arnold Rots - USRA/SAO
|
6 |
// Date: 7 June 1999
|
7 |
// Subsystem: XFF
|
8 |
// Library: ObsCat
|
9 |
// Description: Code for XTime, XTimeRange, XTRList classes
|
10 |
//
|
11 |
//----------------------------------------------------------------------
|
12 |
//
|
13 |
|
14 |
#include <string.h> |
15 |
#include <ctype.h> |
16 |
#include <unistd.h> |
17 |
#include <stdio.h> |
18 |
#include <stdlib.h> |
19 |
#include <math.h> |
20 |
#include <iostream> |
21 |
#include "XTime.h" |
22 |
#define TAIUTC "tai-utc.dat" |
23 |
|
24 |
using namespace std; |
25 |
|
26 |
int XTime::NUMOBJECTS = 0 ; // Number of instantiated XTime objects |
27 |
const double XTime::MJD0 = 2400000.5 ; // JD - MJD |
28 |
const long XTime::MJD1972 = 41317 ; // MJD at 1972 |
29 |
const double XTime::DAY2SEC = 86400.0 ; // Seconds per day |
30 |
const double XTime::SEC2DAY = 1.0 / DAY2SEC ; // Inverse seconds per day |
31 |
const long XTime::MJDREFint = 50814 ; // MJD at 1998.0 |
32 |
const double XTime::MJDREFfr = 0.0 ; // MJD at 1998.0 |
33 |
const double XTime::REFLEAPS = 31.0 ; // Leap seconds at default MJDREF (1998.0 TT) |
34 |
const double XTime::TAI2TT = 32.184 ; // TT - TAI |
35 |
int XTime::NUMLEAPSECS = 0 ; // Leap seconds: 1972 through 2009 |
36 |
long XTime::LEAPSMJD[] = {41317, 41499, 41683, 42048, 42413, 42778, 43144, 43509, 43874, |
37 |
44239, 44786, 45151, 45516, 46247, 47161, 47892, 48257, 48804, |
38 |
49169, 49534, 50083, 50630, 51179, 53736, 54832, 56109} ; |
39 |
double XTime::LEAPSECS[] = {10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, |
40 |
26, 27, 28, 29, 30, 31, 32, 33, 34, 35} ; |
41 |
time_t XTime::WALLCLOCK0 ; // Wallclock time when leap seconds were read
|
42 |
|
43 |
static int daymonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} ; |
44 |
static const char* const month[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", |
45 |
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"} ; |
46 |
|
47 |
//
|
48 |
// ------------------------
|
49 |
// -- XTime::setleaps (void) --
|
50 |
// ------------------------
|
51 |
//
|
52 |
|
53 |
// Description:
|
54 |
// Function to set leap second table
|
55 |
// If it was more than abs(dt) seconds since the
|
56 |
// leap seconds were read, the leap second table
|
57 |
// is refreshed; if dt > 0, only additional leap
|
58 |
// seconds are added; if dt < 0, all leap seconds
|
59 |
// are refreshed. The default is dt=5000000 (about
|
60 |
// two months).
|
61 |
// This is the private method; for the public method
|
62 |
// use void XTime::setLeaps (double dt).
|
63 |
|
64 |
void XTime::setleaps (double dt) |
65 |
{ |
66 |
// Increment the object counter:
|
67 |
NUMOBJECTS++ ; |
68 |
|
69 |
// Now the business of the leap seconds
|
70 |
int refresh = 0 ; |
71 |
int all = dt < 0.0 ; |
72 |
if ( all ) dt = -dt ;
|
73 |
// If they were set before, check whether they expired
|
74 |
if ( NUMLEAPSECS ) {
|
75 |
time_t wallclock1 ; |
76 |
time (&wallclock1) ; |
77 |
if ( difftime (wallclock1, WALLCLOCK0) > dt )
|
78 |
refresh = 1 ;
|
79 |
} |
80 |
else
|
81 |
refresh = 1 ;
|
82 |
|
83 |
// Try to read the leap seconds file
|
84 |
if ( refresh ) {
|
85 |
char *filepath ;
|
86 |
FILE *FF = NULL ;
|
87 |
char lsfile[256] ; |
88 |
int nums = 0 ; |
89 |
|
90 |
// Did the user provide his/her own?
|
91 |
if ( filepath = getenv("TIMING_DIR") ) { |
92 |
sprintf (lsfile, "%s/%s", filepath, TAIUTC) ;
|
93 |
FF = fopen (lsfile, "r") ;
|
94 |
} |
95 |
|
96 |
// Otherwise, the standard file
|
97 |
if ( FF == NULL ) |
98 |
if ( filepath = getenv ("ASC_DATA") ) { |
99 |
sprintf (lsfile, "%s/%s", filepath, TAIUTC) ;
|
100 |
FF = fopen (lsfile, "r") ;
|
101 |
} |
102 |
|
103 |
// If the file is found, read it (only post 1972)
|
104 |
if ( FF ) {
|
105 |
long leapsMD ;
|
106 |
double leapsecs ;
|
107 |
int i ;
|
108 |
while ( fscanf (FF, "%d %*s 1 =JD 24%ld.5 %*s %lg S + (MJD - %*lg) X %*lg %*s", |
109 |
&i, &leapsMD, &leapsecs) == 3 ) {
|
110 |
if ( i > 1970 ) { |
111 |
// Only overwrite existing values when forced to do so
|
112 |
if ( all || ( nums >= NUMLEAPSECS ) ) {
|
113 |
LEAPSMJD[nums] = leapsMD ; |
114 |
LEAPSECS[nums] = leapsecs ; |
115 |
nums++ ; |
116 |
} |
117 |
} |
118 |
} |
119 |
int error = ferror (FF) ;
|
120 |
fclose (FF) ; |
121 |
// If we got fewer leap seconds than before, there must have been an error
|
122 |
if ( ( nums >= NUMLEAPSECS ) && !error ) {
|
123 |
time (&WALLCLOCK0) ; |
124 |
NUMLEAPSECS = nums ; |
125 |
} |
126 |
} |
127 |
|
128 |
// File could not be found; use the ones we know about when coding
|
129 |
else if ( !NUMLEAPSECS ) { |
130 |
nums = 26 ; // Leap seconds: 1972.0 through 2013.0 |
131 |
NUMLEAPSECS = nums ; |
132 |
} |
133 |
|
134 |
} |
135 |
return ;
|
136 |
} |
137 |
|
138 |
//
|
139 |
// -------------------------------------------------------------
|
140 |
// -- XTime::setmyleaps (double *leapval, long mjdi, double mjdf) --
|
141 |
// -------------------------------------------------------------
|
142 |
//
|
143 |
|
144 |
// Description:
|
145 |
// Set the number of leap seconds for time mjdi+mjdf (TT) in leapval.
|
146 |
// mjdf should include timeZero, if applicable.
|
147 |
// Return 1 if mjdi+mjdf falls during a leap second; otherwise 0.
|
148 |
int XTime::setmyleaps (double *leapval, long mjdi, double mjdf) |
149 |
{ |
150 |
int i = NUMLEAPSECS - 1 ; |
151 |
int m = 0 ; |
152 |
double x = (double) mjdi + mjdf - TAI2TT * SEC2DAY ; |
153 |
long j = (long) x ; |
154 |
while ( ( j < LEAPSMJD[i] ) && i )
|
155 |
i-- ; |
156 |
if ( ( (x - LEAPSECS[i]*SEC2DAY) < LEAPSMJD[i] ) && i ) {
|
157 |
i-- ; |
158 |
if ( (LEAPSMJD[i+1] - x) <= SEC2DAY ) |
159 |
m = 1 ;
|
160 |
} |
161 |
*leapval = LEAPSECS[i] ; |
162 |
return m ;
|
163 |
} |
164 |
|
165 |
//
|
166 |
// ---------------------------------------------------------------------------
|
167 |
// -- XTime::set (double tt, TimeSys ts, TimeFormat tf, long mjdi, double mjdf) --
|
168 |
// ---------------------------------------------------------------------------
|
169 |
//
|
170 |
|
171 |
// Description:
|
172 |
// General set function; tt sets time in SECS, MJD, or JD, as
|
173 |
// specified by ts and tf. Allows for setting MJDREF
|
174 |
// (mjdi+mjdf); the default is 50814.0 (1998.0 TT). The default
|
175 |
// for ts is MET, for tf SECS. The defaults for mjdi and mjdf
|
176 |
// are 0 and 0.0. Note that if a new MJDref is specified
|
177 |
// (non-zero), it will be assumed to be in Time System ts.
|
178 |
// I.e., set (x, UTC, SECS) is not the same as set
|
179 |
// (x, UTC, SECS, 50814)
|
180 |
// This method calls
|
181 |
// XTime::set (long, double, TimeSys, TimeFormat, long, double)
|
182 |
void XTime::set (double tt, TimeSys ts, TimeFormat tf, |
183 |
long mjdi, double mjdf) |
184 |
{ |
185 |
double x ;
|
186 |
long k ;
|
187 |
|
188 |
k = (long) tt ;
|
189 |
x = tt - k ; |
190 |
set (k, x, ts, tf, mjdi, mjdf) ; |
191 |
|
192 |
return ;
|
193 |
} |
194 |
|
195 |
//
|
196 |
// --------------------------------------------------------------------------------------
|
197 |
// -- XTime::set (long tti, double ttf, TimeSys ts, TimeFormat tf, long mjdi, double mjdf) --
|
198 |
// --------------------------------------------------------------------------------------
|
199 |
//
|
200 |
|
201 |
// Description:
|
202 |
// Most general set function. tti+ttf sets time in SECS, MJD, or
|
203 |
// JD, as specified by ts and tf. Allows for setting MJDREF
|
204 |
// (mjdi+mjdf); the default is 50814.0 (1998.0 TT).
|
205 |
// The default for ts is TT, for tf MJD. The defaults for mjdi
|
206 |
// and mjdf are 0 and 0.0.
|
207 |
// Note that if a new MJDref is specified (non-zero), it will be
|
208 |
// assumed to be in Time System ts.
|
209 |
// I.e., set (k, x, UTC, SECS) is not the same as
|
210 |
// set (k, x, UTC, SECS, 50814)
|
211 |
void XTime::set (long tti, double ttf, TimeSys ts, TimeFormat tf, |
212 |
long mjdi, double mjdf) |
213 |
{ |
214 |
double total, x ;
|
215 |
long j=0, k ; |
216 |
int i ;
|
217 |
leapflag = 0 ;
|
218 |
|
219 |
// First, set the MJDREF, if specified
|
220 |
if ( mjdi > 1 ) { |
221 |
switch (ts) {
|
222 |
case UTC: {
|
223 |
XTime mt (mjdi, mjdf, ts) ; |
224 |
mt.mjd (&mjdi, &mjdf) ; |
225 |
break ;
|
226 |
} |
227 |
case TAI:
|
228 |
mjdf += TAI2TT * SEC2DAY ; |
229 |
if ( mjdf < 0.0 ) { |
230 |
mjdf++ ; |
231 |
mjdi-- ; |
232 |
} |
233 |
break ;
|
234 |
} |
235 |
MJDrefint = mjdi ; |
236 |
MJDreffr = mjdf ; |
237 |
setmyleaps (&refLeaps, mjdi, mjdf) ; |
238 |
} |
239 |
|
240 |
// total contains the corrections wrt to TT in seconds
|
241 |
total = 0.0 ; |
242 |
|
243 |
// Convert the format to MJD (TT); store in k and x
|
244 |
switch (tf) {
|
245 |
|
246 |
// First JD and MJD
|
247 |
case JD:
|
248 |
tti -= (long) MJD0 ;
|
249 |
ttf -= 0.5 ; |
250 |
case MJD:
|
251 |
k = tti ; |
252 |
x = ttf ; |
253 |
|
254 |
// Build up the corrections to TT, depending on ts
|
255 |
switch (ts) {
|
256 |
case UTC:
|
257 |
i = NUMLEAPSECS - 1 ;
|
258 |
while ( ( k < LEAPSMJD[i] ) && i ) {
|
259 |
i-- ; |
260 |
} |
261 |
if ( ( i < NUMLEAPSECS-1 ) && ( k+1 == LEAPSMJD[i+1] ) && |
262 |
( (LEAPSMJD[i+1] - k + x + timeZero) < SEC2DAY ) && i ) {
|
263 |
i-- ; |
264 |
leapflag = 1 ;
|
265 |
} |
266 |
total += LEAPSECS[i] ; |
267 |
myLeaps = LEAPSECS[i] ; |
268 |
case TAI:
|
269 |
total += TAI2TT ; |
270 |
case TT:
|
271 |
case MET:
|
272 |
break ;
|
273 |
default: // Error in ts; do nothing |
274 |
return ;
|
275 |
} |
276 |
break ;
|
277 |
|
278 |
// Seconds is slightly different since it's relative
|
279 |
// Be careful about precision
|
280 |
case SECS:
|
281 |
k = (long) ((double) tti * SEC2DAY) ; |
282 |
x = (double) tti * SEC2DAY - k ;
|
283 |
x += ttf * SEC2DAY + MJDreffr ; |
284 |
k += MJDrefint ; |
285 |
// Corrections are only needed for UTC, since the reference is now TT
|
286 |
switch (ts) {
|
287 |
case UTC:
|
288 |
// First, subtract the leap seconds for the reference
|
289 |
total -= refLeaps ; |
290 |
// Then add the leap seconds for the time itself
|
291 |
i = NUMLEAPSECS - 1 ;
|
292 |
j = (long) (k + x + timeZero) ;
|
293 |
while ( ( j < LEAPSMJD[i] ) && i ) {
|
294 |
i-- ; |
295 |
} |
296 |
if ( ( (k + x + timeZero - LEAPSMJD[i]) < SEC2DAY ) && i ) {
|
297 |
i-- ; |
298 |
leapflag = 1 ;
|
299 |
} |
300 |
total += LEAPSECS[i] ; |
301 |
myLeaps = LEAPSECS[i] ; |
302 |
case TAI:
|
303 |
case TT:
|
304 |
case MET:
|
305 |
break ;
|
306 |
default: // Error in ts; do nothing |
307 |
return ;
|
308 |
} |
309 |
break ;
|
310 |
default: // Error in tf; do nothing |
311 |
return ;
|
312 |
} |
313 |
|
314 |
// Now we are ready to set the time
|
315 |
x += total * SEC2DAY ; |
316 |
j = (long) x ;
|
317 |
MJDint = k + j ; |
318 |
MJDfr = x - j ; |
319 |
if ( MJDfr < 0.0 ) { |
320 |
MJDfr++ ; |
321 |
MJDint-- ; |
322 |
} |
323 |
// The leap seconds value and flag have already been set for UTC
|
324 |
if ( ts != UTC )
|
325 |
leapflag = setmyleaps (&myLeaps, MJDint, MJDfr+timeZero) ; |
326 |
|
327 |
return ;
|
328 |
} |
329 |
|
330 |
//
|
331 |
// ----------------------------------------------------------------------------
|
332 |
// -- XTime::set (char* date, TimeSys ts, TimeFormat tf, long mjdi, double mjdf) --
|
333 |
// ----------------------------------------------------------------------------
|
334 |
//
|
335 |
|
336 |
// Description:
|
337 |
// General set function from a date string.
|
338 |
// Allows specification of DATE, CALDATE, or FITS formats.
|
339 |
// The defaults for ts, tf, and dec are UTC, DATE, and 0.
|
340 |
// This method calls
|
341 |
// XTime::set (long, double, TimeSys, TimeFormat, long, double)
|
342 |
void XTime::set (const char* date, TimeSys ts, TimeFormat tf, |
343 |
long mjdi, double mjdf) |
344 |
{ |
345 |
long year=0, day=0, hour=0, minute=0 ; |
346 |
double second=0.0 ; |
347 |
int n ;
|
348 |
int m = 0 ; |
349 |
char mn[4] ; |
350 |
|
351 |
switch (tf) {
|
352 |
case DATE:
|
353 |
n = sscanf (date, "%ld:%ld:%ld:%ld:%lg", &year, &day, &hour, &minute, &second) ;
|
354 |
if ( n != 5 ) |
355 |
return ;
|
356 |
break ;
|
357 |
case CALDATE:
|
358 |
n = sscanf (date, "%ld%c%c%c%ld at %ld:%ld:%lg",
|
359 |
&year, mn, mn+1, mn+2, &day, &hour, &minute, &second) ; |
360 |
if ( n != 8 ) |
361 |
return ;
|
362 |
if ( year%4 ) |
363 |
daymonth[1] = 28 ; |
364 |
else
|
365 |
daymonth[1] = 29 ; |
366 |
mn[0] = toupper(mn[0]) ; |
367 |
mn[1] = tolower(mn[1]) ; |
368 |
mn[2] = tolower(mn[2]) ; |
369 |
mn[3] = 0 ; |
370 |
while ( strcmp(mn, month[m]) ) {
|
371 |
if ( m > 11 ) |
372 |
return ;
|
373 |
day += daymonth[m++] ; |
374 |
} |
375 |
break ;
|
376 |
case FITS: {
|
377 |
n = sscanf (date, "%ld-%d-%ldT%ld:%ld:%lg",
|
378 |
&year, &m, &day, &hour, &minute, &second) ; |
379 |
if ( ( n != 6 ) && ( n != 3 ) ) |
380 |
return ;
|
381 |
if ( year%4 ) |
382 |
daymonth[1] = 28 ; |
383 |
else
|
384 |
daymonth[1] = 29 ; |
385 |
m-- ; |
386 |
for (int i=0; i<m; i++) |
387 |
day += daymonth[i] ; |
388 |
break ;
|
389 |
} |
390 |
default:
|
391 |
return ;
|
392 |
} |
393 |
|
394 |
day += (year - 1972) * 365 - 1 ; |
395 |
day += (year - 1969) / 4 ; |
396 |
day += MJD1972 ; |
397 |
second += (double) hour * 3600 + minute * 60 ; |
398 |
second *= SEC2DAY ; |
399 |
|
400 |
set (day, second, ts, MJD, mjdi, mjdf) ; |
401 |
|
402 |
return ;
|
403 |
} |
404 |
|
405 |
//
|
406 |
// -------------------------------------------------
|
407 |
// -- XTime::monDay (const char* date, TimeFormat tf) --
|
408 |
// -------------------------------------------------
|
409 |
//
|
410 |
|
411 |
// Description:
|
412 |
// Convert UTC or TT date string to calendar date string
|
413 |
const char* XTime::monDay (const char* date, TimeFormat tf) { |
414 |
char d[32] ; |
415 |
int year, day ;
|
416 |
int m = 0 ; |
417 |
|
418 |
strcpy (d, date) ; |
419 |
sscanf (d, "%d:%d", &year, &day) ;
|
420 |
if ( year%4 ) |
421 |
daymonth[1] = 28 ; |
422 |
else
|
423 |
daymonth[1] = 29 ; |
424 |
|
425 |
while ( day > daymonth[m] ) {
|
426 |
day -= daymonth[m] ; |
427 |
m++ ; |
428 |
} |
429 |
if ( tf == CALDATE ) {
|
430 |
sprintf (tdate, "%04d%s%02d at ", year, month[m], day) ;
|
431 |
strcpy (tdate+13, d+9) ; |
432 |
} |
433 |
else if ( tf == FITS ) { |
434 |
sprintf (tdate, "%04d-%02d-%02dT", year, m+1, day) ; |
435 |
strcpy (tdate+11, d+9) ; |
436 |
} |
437 |
|
438 |
return ( tdate ) ;
|
439 |
} |
440 |
|
441 |
//
|
442 |
// ----------------------------------------
|
443 |
// -- XTime::get (TimeSys ts, TimeFormat tf) --
|
444 |
// ----------------------------------------
|
445 |
//
|
446 |
|
447 |
// Description:
|
448 |
// Generalized time return function; returns SECS
|
449 |
// (relative to current MJDref), MJD, or JD, as
|
450 |
// specified by ts and tf.
|
451 |
// Default for ts is TT, for tf SECS.
|
452 |
double XTime::get (TimeSys ts, TimeFormat tf) const { |
453 |
double tt=timeZero ;
|
454 |
|
455 |
switch (tf) {
|
456 |
case SECS:
|
457 |
switch (ts) {
|
458 |
case UTC:
|
459 |
tt = getUTC () ; |
460 |
break ;
|
461 |
case TT:
|
462 |
tt = getTT () ; |
463 |
break ;
|
464 |
case TAI:
|
465 |
tt = getTAI () ; |
466 |
break ;
|
467 |
case MET:
|
468 |
tt = getMET () ; |
469 |
break ;
|
470 |
} |
471 |
break ;
|
472 |
case JD:
|
473 |
tt += MJD0 ; |
474 |
case MJD:
|
475 |
switch (ts) {
|
476 |
case UTC:
|
477 |
tt -= myLeaps * SEC2DAY ; |
478 |
case TAI:
|
479 |
tt -= TAI2TT * SEC2DAY ; |
480 |
case MET:
|
481 |
case TT:
|
482 |
tt += MJDint + MJDfr ; |
483 |
break ;
|
484 |
} |
485 |
} |
486 |
return tt ;
|
487 |
} |
488 |
|
489 |
//
|
490 |
// ---------------------------------------------------
|
491 |
// -- XTime::mjd (long *mjdi, double *mjdf, TimeSys ts) --
|
492 |
// ---------------------------------------------------
|
493 |
//
|
494 |
|
495 |
// Description:
|
496 |
// Return MJD (*mjdi+*mjdf) and put integer and fractional parts
|
497 |
// in arguments, for TimeSys ts (default: TT).
|
498 |
double XTime::mjd (long *mjdi, double *mjdf, TimeSys ts) const { |
499 |
|
500 |
switch (ts) {
|
501 |
case TT:
|
502 |
return TTmjd (mjdi, mjdf) ;
|
503 |
case TAI:
|
504 |
return TAImjd (mjdi, mjdf) ;
|
505 |
case UTC:
|
506 |
return UTmjd (mjdi, mjdf) ;
|
507 |
} |
508 |
return 0.0; |
509 |
} |
510 |
|
511 |
//
|
512 |
// -----------------------------------------
|
513 |
// -- XTime::UTmjd (long *mjdi, double *mjdf) --
|
514 |
// -----------------------------------------
|
515 |
//
|
516 |
|
517 |
// Description:
|
518 |
// Return UTC MJD and put integer and fractional parts in
|
519 |
// arguments.
|
520 |
double XTime::UTmjd (long *mjdi, double *mjdf) const { |
521 |
long k = MJDint ;
|
522 |
double x = MJDfr + timeZero - (TAI2TT+myLeaps)*SEC2DAY ;
|
523 |
|
524 |
if ( x < 0.0 ) { |
525 |
x++ ; |
526 |
k-- ; |
527 |
} |
528 |
else if ( x >= 1.0 ) { |
529 |
x-- ; |
530 |
k++ ; |
531 |
} |
532 |
|
533 |
*mjdi = k ; |
534 |
*mjdf = x ; |
535 |
double tt = k + x ;
|
536 |
|
537 |
return tt ;
|
538 |
} |
539 |
|
540 |
//
|
541 |
// -----------------------------------------------------
|
542 |
// -- XTime::getDate (TimeSys ts, TimeFormat tf, int dec) --
|
543 |
// -----------------------------------------------------
|
544 |
//
|
545 |
|
546 |
// Description:
|
547 |
// Generalized date string return function.
|
548 |
// Allows specification of DATE, CALDATE, or FITS formats
|
549 |
// and the number of decimals in the seconds field.
|
550 |
// The defaults for ts, tf, and dec are UTC, DATE, and 0.
|
551 |
const char* XTime::getDate (TimeSys ts, TimeFormat tf, int dec) { |
552 |
long k ;
|
553 |
double x ;
|
554 |
|
555 |
// Get MJD representation
|
556 |
mjd (&k, &x, ts) ; |
557 |
if ( ( ts == UTC ) && leapflag )
|
558 |
x -= SEC2DAY ; |
559 |
while ( x < 0.0 ) { |
560 |
x++ ; |
561 |
k-- ; |
562 |
} |
563 |
while ( x >= 1.0 ) { |
564 |
x-- ; |
565 |
k++ ; |
566 |
} |
567 |
|
568 |
// Divide into year/day/hour/minute/second
|
569 |
int year, day, hour, minute ;
|
570 |
double second ;
|
571 |
double dsec ;
|
572 |
dsec = 0.5 * pow(10.0, (double) -dec) ; |
573 |
|
574 |
// First add dsec; later subtract it; this is to avoid rounding 59.9999 to 60.0
|
575 |
day = k - MJD1972 ; |
576 |
second = x * DAY2SEC + dsec ; |
577 |
int i = 0 ; |
578 |
year = 1972 ;
|
579 |
if ( ( ts == UTC ) && leapflag ) {
|
580 |
second++ ; |
581 |
hour = (int) second / 3600 ; |
582 |
if ( hour > 23 ) hour-- ; |
583 |
second -= hour * 3600.0 ; |
584 |
minute = (int) second / 60 ; |
585 |
if ( minute > 59 ) minute-- ; |
586 |
second -= minute * 60.0 ; |
587 |
} |
588 |
else {
|
589 |
hour = (int) second / 3600 ; |
590 |
second -= hour * 3600.0 ; |
591 |
minute = (int) second / 60 ; |
592 |
second -= minute * 60.0 ; |
593 |
} |
594 |
if ( hour > 23 ) { |
595 |
hour -= 24 ;
|
596 |
day++ ; |
597 |
} |
598 |
second -= dsec ; |
599 |
if ( second < 0.0 ) second = 0.0 ; |
600 |
day++ ; |
601 |
while ( day > 365 ) { |
602 |
if ( !i ) {
|
603 |
if ( day == 366 ) |
604 |
break ;
|
605 |
else
|
606 |
day-- ; |
607 |
} |
608 |
day -= 365 ;
|
609 |
year++ ; |
610 |
i = (i+1)%4 ; |
611 |
} |
612 |
|
613 |
char formt[32], f2[10] ; |
614 |
if ( dec ) {
|
615 |
strcpy (formt, "%4d:%03d:%02d:%02d:%0") ;
|
616 |
sprintf (f2, "%d.%df", dec+3, dec) ; |
617 |
strcat (formt, f2) ; |
618 |
} |
619 |
else
|
620 |
strcpy (formt, "%4d:%03d:%02d:%02d:%02.0f") ;
|
621 |
sprintf (tdate, formt, |
622 |
year, day, hour, minute, second) ; |
623 |
/*
|
624 |
switch (ts) {
|
625 |
case TT:
|
626 |
strcat (tdate, "TT") ;
|
627 |
break ;
|
628 |
case UTC:
|
629 |
strcat (tdate, "UTC") ;
|
630 |
break ;
|
631 |
case MET:
|
632 |
strcat (tdate, "MET") ;
|
633 |
break ;
|
634 |
default:
|
635 |
break ;
|
636 |
}
|
637 |
*/
|
638 |
if ( ( tf == CALDATE ) || ( tf == FITS ) )
|
639 |
return ( monDay (tdate, tf) ) ;
|
640 |
else
|
641 |
return tdate ;
|
642 |
} |
643 |
|
644 |
//
|
645 |
// -------------------------
|
646 |
// -- XTimeRange::setEmpty () --
|
647 |
// -------------------------
|
648 |
//
|
649 |
|
650 |
// Description:
|
651 |
// Determine whether range is empty
|
652 |
void XTimeRange::setEmpty (void) { |
653 |
double t1=start.getMET() ;
|
654 |
double t2=stop.getMET() ;
|
655 |
if ( ( t1 >= t2 ) || ( t1 <= 0.0 ) || ( t2 <= 0.0 ) ) |
656 |
empty = 1 ;
|
657 |
else
|
658 |
empty = 0 ;
|
659 |
return ;
|
660 |
} |
661 |
|
662 |
//
|
663 |
// ---------------------------
|
664 |
// -- XTimeRange::printRange () --
|
665 |
// ---------------------------
|
666 |
//
|
667 |
|
668 |
// Description:
|
669 |
// A two-liner in UTC date format
|
670 |
void XTimeRange::printRange (void) { |
671 |
cout << "---XTimeRange - Empty: " << empty
|
672 |
<< ", Start: " << start.getMET() << " (" << UTStartDate () << ")\n" |
673 |
<< " "
|
674 |
<< " Stop: " << stop.getMET() << " (" << UTStopDate () << ")\n" ; |
675 |
return ;
|
676 |
} |
677 |
//
|
678 |
// ------------------------------
|
679 |
// -- XTimeRange::printRangeCal () --
|
680 |
// ------------------------------
|
681 |
//
|
682 |
|
683 |
// Description:
|
684 |
// A two-liner in UTC calendar date format
|
685 |
void XTimeRange::printRangeCal (void) { |
686 |
cout << "---XTimeRange - Empty: " << empty
|
687 |
<< ", Start: " << start.getMET() << " (" << start.UTCalDate () << ")\n" |
688 |
<< " "
|
689 |
<< " Stop: " << stop.getMET() << " (" << stop.UTCalDate () << ")\n" ; |
690 |
return ;
|
691 |
} |
692 |
|
693 |
//
|
694 |
// -----------------------
|
695 |
// -- XTRList::printList () --
|
696 |
// -----------------------
|
697 |
//
|
698 |
|
699 |
// Description:
|
700 |
// Print list contents in UTC calendar date format
|
701 |
void XTRList::printList (void) { |
702 |
cout << "\nXTRList - Empty: " << empty << ", Number of ranges:: " << numXTRs |
703 |
<< ", List range:\n" ;
|
704 |
listRange.printRange () ; |
705 |
if ( numXTRs ) {
|
706 |
cout << "Member ranges:\n" ;
|
707 |
for (int i=0;i<numXTRs;i++) |
708 |
tr[i].printRange () ; |
709 |
} |
710 |
return ;
|
711 |
} |
712 |
|
713 |
//
|
714 |
// --------------------------
|
715 |
// -- XTRList::printListCal () --
|
716 |
// --------------------------
|
717 |
//
|
718 |
|
719 |
// Description:
|
720 |
// Print list contents in UTC calendar date format
|
721 |
void XTRList::printListCal (void) { |
722 |
cout << "\nXTRList - Empty: " << empty << ", Number of ranges:: " << numXTRs |
723 |
<< ", List range:\n" ;
|
724 |
listRange.printRangeCal () ; |
725 |
if ( numXTRs ) {
|
726 |
cout << "Member ranges:\n" ;
|
727 |
for (int i=0;i<numXTRs;i++) |
728 |
tr[i].printRangeCal () ; |
729 |
} |
730 |
return ;
|
731 |
} |
732 |
|
733 |
//
|
734 |
// ----------------------------
|
735 |
// -- XTRList::XTRList (XTRList) --
|
736 |
// ----------------------------
|
737 |
//
|
738 |
|
739 |
// Description:
|
740 |
// Copy constructor for a new TR list
|
741 |
XTRList::XTRList (const XTRList &trl)
|
742 |
{ |
743 |
numXTRs = trl.numXTRs ; |
744 |
listRange = trl.listRange ; |
745 |
empty = trl.empty ; |
746 |
tr = new XTimeRange[numXTRs] ;
|
747 |
for (int i=0; i<numXTRs; i++) |
748 |
tr[i] = trl.tr[i] ; |
749 |
return ;
|
750 |
} |
751 |
|
752 |
//
|
753 |
// ------------------------------
|
754 |
// -- XTRList::operator= (XTRList) --
|
755 |
// ------------------------------
|
756 |
//
|
757 |
|
758 |
// Description:
|
759 |
// Copy operator for a TR list
|
760 |
XTRList& XTRList::operator= (const XTRList &trl) |
761 |
{ |
762 |
delete [] tr ;
|
763 |
numXTRs = trl.numXTRs ; |
764 |
listRange = trl.listRange ; |
765 |
empty = trl.empty ; |
766 |
tr = new XTimeRange[numXTRs] ;
|
767 |
for (int i=0; i<numXTRs; i++) |
768 |
tr[i] = trl.tr[i] ; |
769 |
return *this ; |
770 |
} |
771 |
|
772 |
|
773 |
//
|
774 |
// -------------------------------------
|
775 |
// -- XTRList::XTRList (XTRList, XTRList) --
|
776 |
// -------------------------------------
|
777 |
//
|
778 |
|
779 |
// Description:
|
780 |
// Construct a new TR list by "AND"ing two existing lists
|
781 |
XTRList::XTRList (const XTRList &trl1, const XTRList &trl2) |
782 |
: numXTRs (1), empty (1), tr (0) { |
783 |
|
784 |
// Trivial cases: if one of them is empty, the result is empty
|
785 |
|
786 |
if ( trl1.isEmpty() || trl2.isEmpty() ) {
|
787 |
numXTRs = 1 ;
|
788 |
empty = 1 ;
|
789 |
tr = new XTimeRange () ;
|
790 |
listRange = *tr ; |
791 |
return ;
|
792 |
} |
793 |
|
794 |
// To minimize work, make sure the second one is the shortest
|
795 |
|
796 |
const XTRList* list1 = &trl1 ;
|
797 |
const XTRList* list2 = &trl2 ;
|
798 |
int nlist1 = list1->numXTRs ;
|
799 |
int nlist2 = list2->numXTRs ;
|
800 |
if ( nlist1 < nlist2 ) {
|
801 |
int i = nlist2 ;
|
802 |
nlist2 = nlist1 ; |
803 |
nlist1 = i ; |
804 |
list1 = list2 ; |
805 |
list2 = &trl1 ; |
806 |
} |
807 |
|
808 |
// Simple case: second list has only one member
|
809 |
|
810 |
if ( nlist2 == 1 ) { |
811 |
XTRList scratchlist (*list1) ; |
812 |
scratchlist.andRange ( list2->tr[0] ) ;
|
813 |
numXTRs = scratchlist.numXTRs ; |
814 |
listRange = scratchlist.listRange ; |
815 |
empty = scratchlist.empty ; |
816 |
tr = new XTimeRange[numXTRs] ;
|
817 |
for (int i=0; i<numXTRs; i++) |
818 |
tr[i] = scratchlist.tr[i] ; |
819 |
return ;
|
820 |
} |
821 |
|
822 |
// The full works: AND each range in list2 with all of list1
|
823 |
// OR the resulting lists
|
824 |
|
825 |
XTRList buildlist ; |
826 |
int i ;
|
827 |
for (i=0;i<nlist2;i++) { |
828 |
XTRList scratchlist (*list1) ; |
829 |
scratchlist.andRange ( list2->tr[i] ) ; |
830 |
buildlist.orList (scratchlist) ; |
831 |
} |
832 |
numXTRs = buildlist.numXTRs ; |
833 |
listRange = buildlist.listRange ; |
834 |
empty = buildlist.empty ; |
835 |
tr = new XTimeRange[numXTRs] ;
|
836 |
for (i=0; i<numXTRs; i++) |
837 |
tr[i] = buildlist.tr[i] ; |
838 |
return ;
|
839 |
} |
840 |
|
841 |
//
|
842 |
// -----------------------------
|
843 |
// -- XTRList::isInRange (XTime&) --
|
844 |
// -----------------------------
|
845 |
//
|
846 |
|
847 |
// Description:
|
848 |
// Return 0 if in range
|
849 |
int XTRList::isInRange (const XTime &T) const { |
850 |
for (int i=0;i<numXTRs;i++) |
851 |
if ( !tr[i].isInRange (T) )
|
852 |
return 0 ; |
853 |
return 1 ; |
854 |
} |
855 |
|
856 |
//
|
857 |
// -----------------------------
|
858 |
// -- XTRList::isInRange (double) --
|
859 |
// -----------------------------
|
860 |
//
|
861 |
|
862 |
// Description:
|
863 |
// Return 0 if in range
|
864 |
int XTRList::isInRange (double t) const { |
865 |
for (int i=0;i<numXTRs;i++) |
866 |
if ( !tr[i].isInRange (t) )
|
867 |
return 0 ; |
868 |
return 1 ; |
869 |
} |
870 |
|
871 |
//
|
872 |
// ----------------------------
|
873 |
// -- XTRList::getRange (XTime&) --
|
874 |
// ----------------------------
|
875 |
//
|
876 |
|
877 |
// Description:
|
878 |
// Return range in which XTime object <T> falls
|
879 |
const XTimeRange* XTRList::getRange (const XTime &T) const { |
880 |
for (int i=0;i<numXTRs;i++) |
881 |
if ( !tr[i].isInRange (T) )
|
882 |
return tr+i ;
|
883 |
return NULL ; |
884 |
} |
885 |
|
886 |
//
|
887 |
// ----------------------------
|
888 |
// -- XTRList::getRange (double) --
|
889 |
// ----------------------------
|
890 |
//
|
891 |
|
892 |
// Description:
|
893 |
// Return range in which MET time <t> falls
|
894 |
const XTimeRange* XTRList::getRange (double t) const { |
895 |
for (int i=0;i<numXTRs;i++) |
896 |
if ( !tr[i].isInRange (t) )
|
897 |
return tr+i ;
|
898 |
return NULL ; |
899 |
} |
900 |
|
901 |
//
|
902 |
// -----------------------
|
903 |
// -- XTRList::totalTime () --
|
904 |
// -----------------------
|
905 |
//
|
906 |
|
907 |
// Description:
|
908 |
// Return total time (in seconds), covered by the list
|
909 |
double XTRList::totalTime (void) const { |
910 |
double tt = 0.0 ; |
911 |
if ( !empty )
|
912 |
for (int i=0;i<numXTRs;i++) |
913 |
tt += tr[i].totalTime () ; |
914 |
return tt ;
|
915 |
} |
916 |
|
917 |
//
|
918 |
// -----------------
|
919 |
// -- XTRList::orList --
|
920 |
// -----------------
|
921 |
//
|
922 |
|
923 |
// Description:
|
924 |
// "OR" in another XTime Range List
|
925 |
void XTRList::orList (const XTRList &trl) { |
926 |
|
927 |
// Do nothing if trl is empty
|
928 |
|
929 |
if ( trl.empty )
|
930 |
return ;
|
931 |
|
932 |
// If *this is empty, replace it by trl
|
933 |
|
934 |
if ( empty ) {
|
935 |
delete [] tr ;
|
936 |
numXTRs = trl.numXTRs ; |
937 |
listRange = trl.listRange ; |
938 |
empty = trl.empty ; |
939 |
tr = new XTimeRange[numXTRs] ;
|
940 |
for (int i=0; i<numXTRs; i++) |
941 |
tr[i] = trl.tr[i] ; |
942 |
} |
943 |
|
944 |
// Do the full thing
|
945 |
|
946 |
else {
|
947 |
int n = trl.numXTRs ;
|
948 |
for (int i=0;i<n;i++) |
949 |
orRange ( trl.tr[i] ) ; |
950 |
} |
951 |
return ;
|
952 |
} |
953 |
|
954 |
//
|
955 |
// ------------------
|
956 |
// -- XTRList::notList --
|
957 |
// ------------------
|
958 |
//
|
959 |
|
960 |
// Description:
|
961 |
// Negate a XTime Range List over a specified time range
|
962 |
void XTRList::notList (const XTimeRange &T) { |
963 |
|
964 |
// If the list was empty, the answer is just T ...
|
965 |
|
966 |
if ( empty ) {
|
967 |
|
968 |
// ... unless, of course, T was empty, too, in which case nothing changes
|
969 |
|
970 |
if ( !T.isEmpty() ) {
|
971 |
*tr = T ; |
972 |
listRange = T ; |
973 |
numXTRs = 1 ;
|
974 |
empty = 0 ;
|
975 |
} |
976 |
} |
977 |
|
978 |
// "Regular" case
|
979 |
|
980 |
else {
|
981 |
XTimeRange* ntr = new XTimeRange[numXTRs+1] ; |
982 |
ntr[0].setStart(1000.0) ; |
983 |
for (int i=0; i<numXTRs; i++) { |
984 |
ntr[i].setStop(tr[i].TStart()) ; |
985 |
ntr[i+1].setStart(tr[i].TStop()) ;
|
986 |
} |
987 |
ntr[numXTRs].setStop(1.0e20) ; |
988 |
numXTRs++ ; |
989 |
delete [] tr ;
|
990 |
tr = ntr ; |
991 |
setListRange () ; |
992 |
andRange (T) ; |
993 |
} |
994 |
return ;
|
995 |
} |
996 |
|
997 |
|
998 |
//
|
999 |
// -------------------
|
1000 |
// -- XTRList::andRange --
|
1001 |
// -------------------
|
1002 |
//
|
1003 |
|
1004 |
// Description:
|
1005 |
// "AND" in an extra XTime Range
|
1006 |
void XTRList::andRange (const XTimeRange &T) { |
1007 |
int startin=0, stopin=0 ; |
1008 |
int startafter=0, stopafter=0 ; |
1009 |
int zap=0 ; |
1010 |
int istart, istop ;
|
1011 |
int i ;
|
1012 |
double tstart = T.METStart () ;
|
1013 |
double tstop = T.METStop () ;
|
1014 |
//
|
1015 |
// First the trivial cases
|
1016 |
//
|
1017 |
if ( empty )
|
1018 |
return ;
|
1019 |
else if ( T.isEmpty () ) |
1020 |
zap = 1 ;
|
1021 |
else if ( ( tstart <= listRange.METStart () ) && |
1022 |
( tstop >= listRange.METStop () ) ) |
1023 |
return ;
|
1024 |
else if ( tstop < listRange.METStart () ) |
1025 |
zap = 1 ;
|
1026 |
else if ( tstart > listRange.METStop () ) |
1027 |
zap = 1 ;
|
1028 |
//
|
1029 |
// See where the start and stop times fall in the existing list
|
1030 |
// (add 1 to the indices)
|
1031 |
else {
|
1032 |
for (i=0;i<numXTRs;i++) { |
1033 |
if ( !startin ) {
|
1034 |
istart = tr[i].isInRange (tstart) ; |
1035 |
if ( !istart )
|
1036 |
startin = i + 1 ;
|
1037 |
else if ( istart > 0 ) |
1038 |
startafter = i + 1 ;
|
1039 |
} |
1040 |
if ( !stopin ) {
|
1041 |
istop = tr[i].isInRange (tstop) ; |
1042 |
if ( !istop )
|
1043 |
stopin = i + 1 ;
|
1044 |
else if ( istop > 0 ) |
1045 |
stopafter = i + 1 ;
|
1046 |
} |
1047 |
} |
1048 |
//
|
1049 |
// Now figure out what to do
|
1050 |
// Which range do we start in?
|
1051 |
//
|
1052 |
if ( startin ) {
|
1053 |
startin -- ; // Correct the index
|
1054 |
tr[startin].setStart (tstart) ; // Adjust the time
|
1055 |
} |
1056 |
|
1057 |
// In between
|
1058 |
else if ( !stopin && ( startafter == stopafter ) ) |
1059 |
zap = 1 ;
|
1060 |
|
1061 |
// Start after
|
1062 |
else
|
1063 |
startin = startafter ; |
1064 |
|
1065 |
// Which range do we stop in?
|
1066 |
if ( !zap ) {
|
1067 |
if ( stopin ) {
|
1068 |
stopin-- ; |
1069 |
tr[stopin].setStop (tstop) ; |
1070 |
} |
1071 |
|
1072 |
// Stop after
|
1073 |
else
|
1074 |
stopin = stopafter - 1 ;
|
1075 |
} |
1076 |
} |
1077 |
|
1078 |
//
|
1079 |
// Calculate the new length
|
1080 |
int newNumXTRs ;
|
1081 |
if ( zap ) {
|
1082 |
newNumXTRs = 1 ;
|
1083 |
empty = 1 ;
|
1084 |
} |
1085 |
else
|
1086 |
newNumXTRs = stopin - startin + 1 ;
|
1087 |
|
1088 |
// No change in number of ranges: done
|
1089 |
if ( numXTRs == newNumXTRs ) {
|
1090 |
if ( zap )
|
1091 |
tr->resetRange (0.0, 0.0) ; |
1092 |
setListRange () ; |
1093 |
return ;
|
1094 |
} |
1095 |
|
1096 |
//
|
1097 |
// Make a new set of ranges
|
1098 |
XTimeRange* newXTR = new XTimeRange[newNumXTRs] ;
|
1099 |
|
1100 |
//
|
1101 |
// Rearrange the ranges
|
1102 |
if ( !zap ) {
|
1103 |
// Now copy the remaining ones
|
1104 |
int j=0 ; |
1105 |
for (i=startin;i<=stopin;i++,j++)
|
1106 |
newXTR[j] = tr[i] ; |
1107 |
} |
1108 |
else
|
1109 |
newXTR->resetRange (0.0, 0.0) ; |
1110 |
|
1111 |
//
|
1112 |
// Exchange the two lists
|
1113 |
delete [] tr ;
|
1114 |
tr = newXTR ; |
1115 |
numXTRs = newNumXTRs ; |
1116 |
setListRange () ; |
1117 |
|
1118 |
return ;
|
1119 |
} |
1120 |
|
1121 |
//
|
1122 |
// ------------------
|
1123 |
// -- XTRList::orRange --
|
1124 |
// ------------------
|
1125 |
//
|
1126 |
|
1127 |
// Description:
|
1128 |
// "OR" in an extra XTime Range
|
1129 |
void XTRList::orRange (const XTimeRange &T) { |
1130 |
int startin=0, stopin=0 ; |
1131 |
int startafter=0, stopafter=0 ; |
1132 |
int before=0, after=0, between=0, straddle=0 ; |
1133 |
int istart, istop ;
|
1134 |
int i ;
|
1135 |
double tstart = T.METStart () ;
|
1136 |
double tstop = T.METStop () ;
|
1137 |
|
1138 |
//
|
1139 |
// Handle the empties first
|
1140 |
//
|
1141 |
if ( T.isEmpty () )
|
1142 |
return ;
|
1143 |
if ( empty ) {
|
1144 |
numXTRs = 1 ;
|
1145 |
empty = 0 ;
|
1146 |
tr[0] = T ;
|
1147 |
listRange = T ; |
1148 |
return ;
|
1149 |
} |
1150 |
|
1151 |
//
|
1152 |
// First the trivial cases
|
1153 |
//
|
1154 |
if ( ( tstart <= listRange.METStart () ) &&
|
1155 |
( tstop >= listRange.METStop () ) ) |
1156 |
straddle = 1 ;
|
1157 |
else if ( tstop < listRange.METStart () ) |
1158 |
before = 1 ;
|
1159 |
else if ( tstart > listRange.METStop () ) |
1160 |
after = 1 ;
|
1161 |
|
1162 |
//
|
1163 |
// See where the start and stop times fall in the existing list
|
1164 |
// (add 1 to the indices)
|
1165 |
else {
|
1166 |
for (i=0;i<numXTRs;i++) { |
1167 |
if ( !startin ) {
|
1168 |
istart = tr[i].isInRange (tstart) ; |
1169 |
if ( !istart )
|
1170 |
startin = i + 1 ;
|
1171 |
else if ( istart > 0 ) |
1172 |
startafter = i + 1 ;
|
1173 |
} |
1174 |
if ( !stopin ) {
|
1175 |
istop = tr[i].isInRange (tstop) ; |
1176 |
if ( !istop )
|
1177 |
stopin = i + 1 ;
|
1178 |
else if ( istop > 0 ) |
1179 |
stopafter = i + 1 ;
|
1180 |
} |
1181 |
} |
1182 |
//
|
1183 |
// Now figure out what to do
|
1184 |
// Which range do we start in?
|
1185 |
//
|
1186 |
if ( startin ) {
|
1187 |
if ( startin == stopin ) // If we're stopping in the same one, return |
1188 |
return ;
|
1189 |
startin -- ; // Correct the index
|
1190 |
} |
1191 |
|
1192 |
// In between
|
1193 |
else if ( !stopin && ( startafter == stopafter ) ) |
1194 |
between = stopafter ; |
1195 |
|
1196 |
// Somebody's start time needs to be adjusted
|
1197 |
else {
|
1198 |
startin = startafter ; |
1199 |
tr[startin].setStart (tstart) ; |
1200 |
} |
1201 |
|
1202 |
// Which range do we stop in?
|
1203 |
if ( stopin )
|
1204 |
stopin-- ; |
1205 |
// Somebody's stop time needs to be adjusted
|
1206 |
else
|
1207 |
if ( stopafter ) {
|
1208 |
stopin = stopafter - 1 ;
|
1209 |
tr[stopin].setStop (tstop) ; |
1210 |
} |
1211 |
} |
1212 |
|
1213 |
//
|
1214 |
// The range list must now be non-empty
|
1215 |
empty = 0 ;
|
1216 |
|
1217 |
//
|
1218 |
// Calculate the new length
|
1219 |
int newNumXTRs ;
|
1220 |
if ( before + after + between )
|
1221 |
newNumXTRs = numXTRs + 1 ;
|
1222 |
else if ( straddle ) |
1223 |
newNumXTRs = 1;
|
1224 |
else
|
1225 |
newNumXTRs = numXTRs - stopin + startin ; |
1226 |
|
1227 |
// No change in number of ranges: done
|
1228 |
if ( numXTRs == newNumXTRs ) {
|
1229 |
if ( straddle )
|
1230 |
tr[0] = T ;
|
1231 |
setListRange () ; |
1232 |
return ;
|
1233 |
} |
1234 |
|
1235 |
//
|
1236 |
// Make a new set of ranges
|
1237 |
XTimeRange* newXTR = new XTimeRange[newNumXTRs] ;
|
1238 |
|
1239 |
//
|
1240 |
// Extra range before
|
1241 |
if ( before ) {
|
1242 |
newXTR[0] = T ;
|
1243 |
for (i=0;i<numXTRs;i++) |
1244 |
newXTR[i+1] = tr[i] ;
|
1245 |
} |
1246 |
|
1247 |
//
|
1248 |
// Extra range after
|
1249 |
else if ( after ) { |
1250 |
for (i=0;i<numXTRs;i++) |
1251 |
newXTR[i] = tr[i] ; |
1252 |
newXTR[numXTRs] = T ; |
1253 |
} |
1254 |
|
1255 |
//
|
1256 |
// Straddling range
|
1257 |
else if ( straddle ) |
1258 |
newXTR[0] = T ;
|
1259 |
|
1260 |
//
|
1261 |
// Extra range in between
|
1262 |
else if ( between ) { |
1263 |
for (i=0;i<between;i++) |
1264 |
newXTR[i] = tr[i] ; |
1265 |
newXTR[between] = T ; |
1266 |
for (i=between;i<numXTRs;i++)
|
1267 |
newXTR[i+1] = tr[i] ;
|
1268 |
} |
1269 |
|
1270 |
//
|
1271 |
// Rearrange the ranges
|
1272 |
else {
|
1273 |
// Cover the new part in a single range
|
1274 |
tr[stopin].setStart (tr[startin].METStart()) ; |
1275 |
// Now copy the remaining ones
|
1276 |
int j=0 ; |
1277 |
for (i=0;i<startin;i++,j++) |
1278 |
newXTR[j] = tr[i] ; |
1279 |
for (i=stopin;i<numXTRs;i++,j++)
|
1280 |
newXTR[j] = tr[i] ; |
1281 |
} |
1282 |
|
1283 |
//
|
1284 |
// Exchange the two lists
|
1285 |
delete [] tr ;
|
1286 |
tr = newXTR ; |
1287 |
numXTRs = newNumXTRs ; |
1288 |
setListRange () ; |
1289 |
|
1290 |
return ;
|
1291 |
} |
1292 |
|
1293 |
//
|
1294 |
// -----------------------
|
1295 |
// -- XTRList::setListRange --
|
1296 |
// -----------------------
|
1297 |
//
|
1298 |
|
1299 |
// Description:
|
1300 |
// Update the list range
|
1301 |
void XTRList::setListRange (void) { |
1302 |
int i, j, remove=0 ; |
1303 |
|
1304 |
if ( numXTRs )
|
1305 |
empty = 0 ;
|
1306 |
for (i=0; i<numXTRs; i++) |
1307 |
if ( tr[i].isEmpty() )
|
1308 |
remove++ ; |
1309 |
if ( remove ) {
|
1310 |
if ( remove >= numXTRs ) {
|
1311 |
numXTRs = 0 ;
|
1312 |
empty = 1 ;
|
1313 |
} |
1314 |
else {
|
1315 |
XTimeRange* newXTR = new XTimeRange[numXTRs - remove] ;
|
1316 |
for (i=0, j=0; i<numXTRs; i++) |
1317 |
if ( !tr[i].isEmpty() )
|
1318 |
newXTR[j++] = tr[i] ; |
1319 |
delete [] tr ;
|
1320 |
tr = newXTR ; |
1321 |
numXTRs -= remove ; |
1322 |
empty = 0 ;
|
1323 |
} |
1324 |
} |
1325 |
|
1326 |
if ( !empty )
|
1327 |
listRange.resetRange (tr[0].METStart(), tr[numXTRs-1].METStop()) ; |
1328 |
else
|
1329 |
listRange.resetRange (0.0, -1.0) ; |
1330 |
} |