Skip to content

Commit 5c362ca

Browse files
committed
Amended pull request with feedback
Hi, I've implemented the feedback given for this PR. Please review!
1 parent 9051000 commit 5c362ca

5 files changed

Lines changed: 112 additions & 113 deletions

File tree

kessler/cdm.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,10 @@ def set_header(self, key, value):
196196
if key in self._keys_header:
197197
if key in self._keys_with_dates:
198198
# We have a field with a date string as the value. Check if the string is in the format needed by the CCSDS 508.0-B-1 standard
199-
timeFormat = time_utils.getCcsdsTimeFormat(value)
199+
timeFormat = util.getCcsdsTimeFormat(value)
200200
idx = timeFormat.find('DDD')
201201
if idx!=-1:
202-
[DateNum, DateVec] = time_utils.DOY2Date(value[idx:idx+3], value[0:4])
203-
value = str(DateVec[0]) +'-' + str(DateVec[1]) + '-' + str(DateVec[2]) + 'T' + value[idx+4:-1] #figure this out!!!
202+
value = util.DOY2Date(value, value[idx:idx+3], value[0:4], idx)
204203
try:
205204
_ = datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%f')
206205
except Exception as e:

kessler/time_utils.py

Lines changed: 0 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1 @@
11
import datetime
2-
def getCcsdsTimeFormat(timeString):
3-
'''
4-
Adapted by Andrew Ng, 18/3/2022.
5-
Original MATLAB source code found at: https://github.com/nasa/CARA_Analysis_Tools/blob/master/two-dimension_Pc/Main/TransformationCode/TimeTransformations/getCcsdsTimeFormat.m
6-
The CCSDS time format is required to be of the general form
7-
yyyy-[mm-dd|ddd]THH:MM:SS[.F*][Z]
8-
(1) The date and time fields are separated by a "T".
9-
(2) The date field has a four digit year followed by either a two digit
10-
month and two digit day, or a three digit day-of-year.
11-
(3) The year, month, day, and day-of-year fields are separated by a dash.
12-
(4) The hours, minutes and seconds fields are each two digits separated
13-
by colons.
14-
(5) The fraction of seconds is optional and can have any number of
15-
digits.
16-
(6) If a fraction of seconds is provided, it is separated from the two
17-
digit seconds by a period.
18-
(7) The time string can end with an optional "Z" time zone indicator
19-
'''
20-
timeFormat = []
21-
numT = timeString.count('T')
22-
if numT == -1:
23-
# Case when this is 'T' does not exist in timeString
24-
print(f"*** Error -- Invalid CCSDS time string: {timeString}")
25-
print(f" No 'T' separator found between date and time portions of the string\n")
26-
return
27-
elif numT > 1:
28-
print(f"*** Error -- Invalid CCSDS time string: {timeString} \n")
29-
print(f" More than one 'T' separator found between date and time portions of the string\n")
30-
return
31-
idxT = timeString.find('T')
32-
if idxT ==10:
33-
timeFormat = "yyyy-mm-ddTHH:MM:SS"
34-
elif idxT ==8:
35-
timeFormat = "yyyy-DDDTHH:MM:SS"
36-
else:
37-
print(f"*** Error -- Invalid CCSDS time string: {timeString} \n", timeString)
38-
print(f" Date format not one of yyyy-mm-dd or yyyy-DDD\n")
39-
return
40-
# % Check if 'Z' time zone indicator appended to the string
41-
if timeString[-1]=='Z':
42-
zOpt = True
43-
else:
44-
zOpt = False
45-
# % Find location of the fraction of seconds decimal separator
46-
numDecimal = timeString.count('.')
47-
if numDecimal > 1:
48-
print(f"*** Error -- Invalid CCSDS time string: {timeString} \n")
49-
print(f" More than one fraction of seconds decimal separator ('.') found.\n")
50-
timeFormat = []
51-
return
52-
idxDecimal = timeString.find('.')
53-
nfrac = 0
54-
if numDecimal != 0:
55-
if zOpt:
56-
nfrac = len(timeString) - 1 - idxDecimal -1
57-
else:
58-
nfrac = len(timeString) - 1 - idxDecimal
59-
if nfrac > 0:
60-
fracStr = '.' + ('F'*nfrac)
61-
else:
62-
fracStr = ""
63-
if zOpt:
64-
fracStr = fracStr+'Z'
65-
timeFormat = timeFormat+fracStr
66-
return timeFormat
67-
68-
def DOY2Date(DOY, YEAR):
69-
'''
70-
Written by Andrew Ng, 18/03/2022,
71-
Based on source code @ https://github.com/nasa/CARA_Analysis_Tools/blob/master/two-dimension_Pc/Main/TransformationCode/TimeTransformations/DOY2Date.m
72-
Use the datetime python package.
73-
DOY2DATE - Converts Day of Year (DOY) to date number and full
74-
calendar date.
75-
76-
'''
77-
# Calculate datetime format
78-
DateNum = datetime.datetime(int(YEAR), 1, 1) + datetime.timedelta(int(DOY) - 1)
79-
# Split datetime object into a date list
80-
DateVec = [DateNum.year, DateNum.month, DateNum.day, DateNum.hour, DateNum.minute]
81-
return DateNum, DateVec

kessler/util.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,3 +348,88 @@ def progress_bar_end(message=None):
348348
print()
349349
if message is not None:
350350
print(message)
351+
352+
def getCcsdsTimeFormat(time_string):
353+
'''
354+
Adapted by Andrew Ng, 18/3/2022.
355+
Original MATLAB source code found at: https://github.com/nasa/CARA_Analysis_Tools/blob/master/two-dimension_Pc/Main/TransformationCode/TimeTransformations/getCcsdsTimeFormat.m
356+
The CCSDS time format is required to be of the general form
357+
yyyy-[mm-dd|ddd]THH:MM:SS[.F*][Z]
358+
(1) The date and time fields are separated by a "T".
359+
(2) The date field has a four digit year followed by either a two digit
360+
month and two digit day, or a three digit day-of-year.
361+
(3) The year, month, day, and day-of-year fields are separated by a dash.
362+
(4) The hours, minutes and seconds fields are each two digits separated
363+
by colons.
364+
(5) The fraction of seconds is optional and can have any number of
365+
digits.
366+
(6) If a fraction of seconds is provided, it is separated from the two
367+
digit seconds by a period.
368+
(7) The time string can end with an optional "Z" time zone indicator
369+
370+
Args:
371+
- time)
372+
'''
373+
time_format = []
374+
numT = time_string.count('T')
375+
if numT == -1:
376+
# Case when this is 'T' does not exist in time_string
377+
raise RuntimeError(f"*** Error -- Invalid CCSDS time string: {time_string}\nNo 'T' separator found between date and time portions of the string")
378+
elif numT > 1:
379+
raise RuntimeError(f"*** Error -- Invalid CCSDS time string: {time_string} \nMore than one 'T' separator found between date and time portions of the string")
380+
idx_T = time_string.find('T')
381+
if idx_T ==10:
382+
time_format = "yyyy-mm-ddTHH:MM:SS"
383+
elif idx_T ==8:
384+
time_format = "yyyy-DDDTHH:MM:SS"
385+
else:
386+
raise RuntimeError(f"*** Error -- Invalid CCSDS time string: {time_string} \nDate format not one of yyyy-mm-dd or yyyy-DDD.\n")
387+
# % Check if 'Z' time zone indicator appended to the string
388+
if time_string[-1]=='Z':
389+
zOpt = True
390+
else:
391+
zOpt = False
392+
# % Find location of the fraction of seconds decimal separator
393+
num_decimal = time_string.count('.')
394+
if num_decimal > 1:
395+
#time_format = []
396+
raise RuntimeError(f"*** Error -- Invalid CCSDS time string: {time_string}\nMore than one fraction of seconds decimal separator ('.') found.\n")
397+
idx_decimal = time_string.find('.')
398+
nfrac = 0
399+
if num_decimal != 0:
400+
if zOpt:
401+
nfrac = len(time_string) - 1 - idx_decimal -1
402+
else:
403+
nfrac = len(time_string) - 1 - idx_decimal
404+
if nfrac > 0:
405+
frac_str = '.' + ('F'*nfrac)
406+
else:
407+
frac_str = ""
408+
if zOpt:
409+
frac_str = frac_str+'Z'
410+
time_format = time_format + frac_str
411+
return time_format
412+
413+
def DOY2Date(value,DOY, YEAR, idx):
414+
'''
415+
Written by Andrew Ng, 18/03/2022,
416+
Based on source code @ https://github.com/nasa/CARA_Analysis_Tools/blob/master/two-dimension_Pc/Main/TransformationCode/TimeTransformations/DOY2Date.m
417+
Use the datetime python package.
418+
DOY2DATE - Converts Day of Year (DOY) date format to date format.
419+
420+
Args:
421+
- value(``str``): Original date time string with day of year format "YYYY-DDDTHH:MM:SS.ff"
422+
- DOY (``str``): The day of year in the DOY format.
423+
- YEAR (``str``): The year.
424+
- idx (``int``): Index of the start of the original "value" string at which characters 'DDD' are found.
425+
Returns:
426+
-value (``str``): Transformed date in traditional date format. i.e.: "YYYY-mm-ddTHH:MM:SS.ff"
427+
428+
'''
429+
# Calculate datetime format
430+
date_num = datetime.datetime(int(YEAR), 1, 1) + datetime.timedelta(int(DOY) - 1)
431+
# Split datetime object into a date list
432+
date_vec = [date_num.year, date_num.month, date_num.day, date_num.hour, date_num.minute]
433+
value = str(date_vec[0]) +'-' + str(date_vec[1]) + '-' + str(date_vec[2]) + 'T' + value[idx+4:-1]
434+
435+
return value

tests/test_time_utils.py

Lines changed: 0 additions & 30 deletions
This file was deleted.

tests/test_util.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,28 @@ def test_from_cartesian_to_rtn_2(self):
111111
state_rtn, _ = kessler.util.from_cartesian_to_rtn(state_xyz)
112112
self.assertAlmostEqual(np.linalg.norm(state_xyz[0]), np.linalg.norm(state_rtn[0]), places=1)
113113
self.assertAlmostEqual(np.linalg.norm(state_xyz[1]), np.linalg.norm(state_rtn[1]), places=1)
114+
115+
def test_getCcsdsTimeFormat(self):
116+
# This test is written by Andrew Ng, 19/03/22. It makes use of example CDMs provided by the NASA CARA
117+
# analysis repo at https://github.com/nasa/CARA_Analysis_Tools/tree/master/two-dimension_Pc/UnitTest/InputFiles.
118+
test_case1 = "2000-01-01T00:00:00.000" #From AlfanoTestCase11.cdm
119+
test_case2 = "2018-229T13:56:33.000" # From DensityDecorrelationTestCaseCDM.txt
120+
test_case1_correct = "yyyy-mm-ddTHH:MM:SS.FFF"
121+
test_case2_correct = "yyyy-DDDTHH:MM:SS.FFF"
122+
123+
self.assertEqual(kessler.util.getCcsdsTimeFormat(test_case1), test_case1_correct)
124+
self.assertEqual(kessler.util.getCcsdsTimeFormat(test_case2), test_case2_correct)
125+
def test_DOY2Date(self):
126+
# This test is written by Andrew Ng, 19/03/22. It makes use of example CDMs provided by the NASA CARA
127+
# analysis repo at https://github.com/nasa/CARA_Analysis_Tools/tree/master/two-dimension_Pc/UnitTest/InputFiles.
128+
example1 = "2010-202T12:25:19.000" # From SingleCovTestCase1-4.cdm
129+
example2 = "2018-229T13:56:33.000" # From DensityDecorrelationTestCaseCDM.txt
130+
DOY_1 = example1[5:5+3]
131+
Year_1= example1[0:4]
132+
DOY_2 = example2[5:5+3]
133+
Year_2= example2[0:4]
134+
test_case1_correct = "2010-7-21T12:25:19.00"
135+
test_case2_correct = "2018-8-17T13:56:33.00"
136+
self.assertEqual(kessler.util.DOY2Date(example1, DOY_1, Year_1, 5), test_case1_correct)
137+
self.assertEqual(kessler.util.DOY2Date(example2, DOY_2, Year_2, 5), test_case2_correct)
138+

0 commit comments

Comments
 (0)