1#!/usr/bin/env python3
  2"""Test AUX data file ingestion decoding as part of CHART-EPSSG decoding and ingestion function.
  3
  4These tests verify the following are Fac. req IDs and Service Def. Req (which
  5include reqs that are verified by the existance of these auto tests):
  6    REQ_IFC_2010: MONA-A&R-410
  7    REQ_ING_050: MONA-A&R-130
  8    REQ_ING_3010: MONA-A&R-410
  9
 10    Dev reqs
 11    REQ_TST_010: MONA-TST-0010
 12    REQ_TST_020: MONA-TST-0020
 13"""
 14
 15import sys
 16from datetime import datetime
 17from lxml import etree
 18import pytest
 19# import pytest_pgsql
 20
 21from chartepssg import project  # must come first
 22from chart.common.path import Path
 23from chart.common.log import init_log
 24from chart.common.traits import is_listlike
 25from chart.common.test_utils import show
 26from chart.common.test_utils import compare
 27from chart.project import settings
 28from chart.project import SID
 29from chart.common.xml import XMLElement
 30from chart.common.test_utils import compare
 31from chartepssg.alg.settings import scid_to_sid
 32from chartepssg.alg import orbit4ant_ingester
 33from chartepssg.alg import predicted_orbit_ingester
 34
 35
 36def print_out(msg, obj):
 37    out = msg.format(obj)
 38    out += '\n'
 39    sys.stdout.write(out)
 40
 41
 42EPSSGA_SID = SID('EPSSGA')
 43EPSSGB_SID = SID('EPSSGB')
 44
 45PROJECT_ROOT_DIR = settings.PROJECT_HOME_DIR.parent
 46AUX_PRODUCT_DIR = PROJECT_ROOT_DIR.joinpath('tests', 'testdata', 'aux')
 47
 48OEMORBPRED_FILE = 'ORB_PRED/SGA1_FDP_FDS__OPE_OEM________G20210421100627Z_S20210421000000Z_E20210428000000Z.xml'
 49PREDICTED_ORB_FILE = 'PRED_ORB/SGA1_FDP_FDS__OPE_PRED_ORB___G20210415132921Z_S20210415000000Z_E20210416120000Z.EOF'
 50
 51SATMASSREP_FILE = 'MASS_REPO/SGA1_FDP_FDS__OPE_MASS_REPO__G20220628140419Z_S20220628140419Z_E20220628140419Z.txt'
 52
 53MANOHIST_FILE = 'MANO_HIST/SGB1_FDP_FDS__OPE_MANO_HIST__G20220628145251Z_S20220503135959Z_E20220706150000Z.txt'
 54
 55MANOPREDIC_FILE = 'MANO_PRED/SGA1_FDP_FDS__OPE_MANO_PRED__G20220615123845Z_S20220622150000Z_E20220622150000Z.txt'
 56
 57#@pytest.mark.skip
 58def test_ORBIT4ANT_decoder():
 59    """Decoder test for ORBIT4ANT aux files.
 60    Compare product file decoding against expected tuple values """
 61
 62    # From visual inspection we have the followwing first and last value in the test file
 63    # first entry
 64    OSV = """
 65        <stateVector>
 66            <EPOCH>2021-04-21T00:00:00.000</EPOCH>
 67            <X> 3.016743752950E+03</X>
 68            <Y>-5.926262342904E+03</Y>
 69            <Z> 2.613202547095E+03</Z>
 70            <X_DOT>-2.678854791139E+00</X_DOT>
 71            <Y_DOT> 1.536418802269E+00</Y_DOT>
 72            <Z_DOT> 6.855073654454E+00</Z_DOT>
 73        </stateVector>
 74    """
 75
 76    sv_elem = XMLElement(elem=etree.fromstring(OSV))
 77    expected_result_1st = orbit4ant_ingester.OrbitPred(
 78        sid=EPSSGA_SID,
 79        epoch=sv_elem.parse_datetime(orbit4ant_ingester.ELEM_EPOCH),
 80        X=sv_elem.parse_float(orbit4ant_ingester.ELEM_X),
 81        Y=sv_elem.parse_float(orbit4ant_ingester.ELEM_Y),
 82        Z=sv_elem.parse_float(orbit4ant_ingester.ELEM_Z),
 83        X_DOT=sv_elem.parse_float(orbit4ant_ingester.ELEM_X_DOT),
 84        Y_DOT=sv_elem.parse_float(orbit4ant_ingester.ELEM_Y_DOT),
 85        Z_DOT=sv_elem.parse_float(orbit4ant_ingester.ELEM_Z_DOT)
 86    )
 87
 88    # last entry
 89    OSV = """
 90            <stateVector>
 91                <EPOCH>2021-04-28T00:00:00.000</EPOCH>
 92                <X>-3.627304613302E+03</X>
 93                <Y> 5.946270489729E+03</Y>
 94                <Z> 3.681271215740E+02</Z>
 95                <X_DOT> 1.265486358023E+00</X_DOT>
 96                <Y_DOT> 1.110315564701E+00</Y_DOT>
 97                <Z_DOT>-7.513939797068E+00</Z_DOT>
 98            </stateVector>
 99        """
100
101    sv_elem = XMLElement(elem=etree.fromstring(OSV))
102    expected_result_last = orbit4ant_ingester.OrbitPred(
103        sid=EPSSGA_SID,
104        epoch=sv_elem.parse_datetime(orbit4ant_ingester.ELEM_EPOCH),
105        X=sv_elem.parse_float(orbit4ant_ingester.ELEM_X),
106        Y=sv_elem.parse_float(orbit4ant_ingester.ELEM_Y),
107        Z=sv_elem.parse_float(orbit4ant_ingester.ELEM_Z),
108        X_DOT=sv_elem.parse_float(orbit4ant_ingester.ELEM_X_DOT),
109        Y_DOT=sv_elem.parse_float(orbit4ant_ingester.ELEM_Y_DOT),
110        Z_DOT=sv_elem.parse_float(orbit4ant_ingester.ELEM_Z_DOT)
111    )
112
113    # decode file
114    ENTRY_COUNT = 505
115    actual_results = list(orbit4ant_ingester.parse_orbitpred(AUX_PRODUCT_DIR.joinpath(OEMORBPRED_FILE)))
116
117    assert ENTRY_COUNT == len(actual_results)
118    assert actual_results[0] == expected_result_1st
119    print_out("OEMORBPRED decoder test passed for first result: {}", expected_result_1st)
120    assert actual_results[ENTRY_COUNT-1] == expected_result_last
121    print_out("OEMORBPRED decoder test passed for last result: {}", expected_result_last)
122
123#@pytest.mark.skip
124def test_PRED_ORBIT_decoder():
125    """Decoder test for PRED_ORB aux files data
126    Compare product file decoding against expected tuple values """
127
128    # From visual inspection we have the followwing first and last value in the test file
129    # added a namespace to be consistent with the XML source files and ingester
130    # first entry
131
132    OSV = """
133        <OSV xmlns="http://eop-cfi.esa.int/CFI">
134            <TAI>TAI=2021-04-15T00:00:37.000000</TAI>
135            <UTC>UTC=2021-04-15T00:00:00.000000</UTC>
136            <UT1>UT1=2021-04-15T00:00:00.000000</UT1>
137            <Absolute_Orbit>+00014</Absolute_Orbit>
138            <X unit="m">+0667217.143</X>
139            <Y unit="m">+0869581.672</Y>
140            <Z unit="m">+7103154.990</Z>
141            <VX unit="m/s">+5895.659566</VX>
142            <VY unit="m/s">-4426.056142</VY>
143            <VZ unit="m/s">-0011.947906</VZ>
144            <Quality>0000000000000</Quality>
145        </OSV>
146        """
147
148    sv_elem = XMLElement(elem=etree.fromstring(OSV))
149    expected_result_1st = predicted_orbit_ingester.PredictedOrbit(
150        sid=EPSSGA_SID,
151        sensing_time=sv_elem.parse_datetime(predicted_orbit_ingester.ELEM_UTC),
152        X=sv_elem.parse_float(predicted_orbit_ingester.ELEM_X),
153        Y=sv_elem.parse_float(predicted_orbit_ingester.ELEM_Y),
154        Z=sv_elem.parse_float(predicted_orbit_ingester.ELEM_Z),
155        VX=sv_elem.parse_float(predicted_orbit_ingester.ELEM_VX),
156        VY=sv_elem.parse_float(predicted_orbit_ingester.ELEM_VY),
157        VZ=sv_elem.parse_float(predicted_orbit_ingester.ELEM_VZ)
158        )
159
160    # added a namespace to be consistent with the XML source files and ingester
161    # last entry
162    OSV = """
163        <OSV xmlns="http://eop-cfi.esa.int/CFI">
164            <TAI>TAI=2021-04-16T12:00:37.000000</TAI>
165            <UTC>UTC=2021-04-16T12:00:00.000000</UTC>
166            <UT1>UT1=2021-04-16T12:00:00.000000</UT1>
167            <Absolute_Orbit>+00036</Absolute_Orbit>
168            <X unit="m">-1101181.394</X>
169            <Y unit="m">+2063287.497</Y>
170            <Z unit="m">+6793192.289</Z>
171            <VX unit="m/s">+5943.955397</VX>
172            <VY unit="m/s">-3802.700647</VY>
173            <VZ unit="m/s">+2147.390705</VZ>
174            <Quality>0000000000000</Quality>
175        </OSV>
176    """
177
178    sv_elem = XMLElement(elem=etree.fromstring(OSV))
179    expected_result_last = predicted_orbit_ingester.PredictedOrbit(
180        sid=EPSSGA_SID,
181        sensing_time=sv_elem.parse_datetime(predicted_orbit_ingester.ELEM_UTC),
182        X=sv_elem.parse_float(predicted_orbit_ingester.ELEM_X),
183        Y=sv_elem.parse_float(predicted_orbit_ingester.ELEM_Y),
184        Z=sv_elem.parse_float(predicted_orbit_ingester.ELEM_Z),
185        VX=sv_elem.parse_float(predicted_orbit_ingester.ELEM_VX),
186        VY=sv_elem.parse_float(predicted_orbit_ingester.ELEM_VY),
187        VZ=sv_elem.parse_float(predicted_orbit_ingester.ELEM_VZ)
188    )
189
190    # decode file
191    ENTRY_COUNT = 109
192    actual_results = list(predicted_orbit_ingester.parse_predicted_orbit(AUX_PRODUCT_DIR.joinpath(PREDICTED_ORB_FILE)))
193
194    assert ENTRY_COUNT == len(actual_results)
195    assert actual_results[0] == expected_result_1st
196    print_out("PRED_ORB decoder test passed for first result: {}", expected_result_1st)
197    assert actual_results[ENTRY_COUNT-1] == expected_result_last
198    print_out("PRED_ORB decoder test passed for last result: {}", expected_result_last)
199
200
201def test_SATMASSREP_decoder():
202    """Decoder test for SATMASSREP aux files.
203    Compare product file decoding against expected tuple values """
204    from chartepssg.alg import satmassrep_ingester
205
206    # From visual inspection we have the followwing value in the test file
207    # SGA1 MASS PROPERTIES COMPUTED ON 2022-06-28T14:04:19
208     # 2022-06-28T14:04:19 CALCULATION DATE
209      # 2.536 XS CO-ORDINATE (METER)
210     # -0.129 YS CO-ORDINATE (METER)
211      # 0.221 ZS CO-ORDINATE (METER)
212     # 1179.999 TOTAL S/C MASS (KG)
213     # 166.523 FUEL MASS (KG)
214      # 1581.8 INERTIA XX (M2.KG)
215      # 3832.1 INERTIA YY (M2.KG)
216      # 5080.9 INERTIA ZZ (M2.KG)
217      # -415.7 INERTIA XY (M2.KG)
218    #    18.7 INERTIA YZ (M2.KG)
219    #    14.7 INERTIA ZX (M2.KG)
220    expected_result = satmassrep_ingester.Report(
221        #sid=scid_to_sid('SGA1'),
222        # calc_date=datetime.strptime('2023-06-21T16:00:00', satmassrep_ingester.CALC_DATE_FORMAT),
223        calc_date=datetime(2022,6,28,14,4,19),
224        xs=2.536, ys=-0.129, zs=0.221,
225        total_mass=1179.999, fuel_mass=166.523,
226        i_xx=1581.8, i_yy=3832.1, i_zz=5080.9,
227        i_xy=-415.7, i_yz=18.7, i_zx=14.7)
228
229    # decode file
230    actual_result = satmassrep_ingester.parse_report(AUX_PRODUCT_DIR.joinpath(SATMASSREP_FILE))
231
232    compare(actual_result, expected_result)
233    # assert actual_result == expected_result
234    print_out("SATMASSREP decoder test passed for result: {}", expected_result)
235
236
237
238def test_MANOHIST_decoder():
239    """Decoder test for MANOHIST aux files.
240    Compare product file decoding against expected tuple values """
241
242    from chartepssg.alg import manohist_ingester
243
244    #sid = scid_to_sid('SGB1')
245     # From visual inspection we have the followwing first and last value in the test file
246    # first entry
247    # 2022/05/03-13:59:59.228     0.00000000D+00 0.11655693D-04 0.00000000D+00    1    1
248
249    expected_result_1st = manohist_ingester.Manoeuvre(
250    #    sid=sid,
251        # datetime.strptime('2016/02/22-09:29:35.000', manohist_ingester.EPOCH_FORMAT),
252        epoch=datetime(2022,5,3,13,59,59,228000),
253        acc_comp_1=0.0,
254        acc_comp_2=0.11655693E-04,
255        acc_comp_3=0.0,
256        flag=1)
257
258    # last entry
259    # 2019/12/11-12:11:00.810    -0.49240007D-08 0.13296058D-07 0.25735859D-05    0
260    expected_result_last = manohist_ingester.Manoeuvre(
261    #    sid=sid,
262        # datetime.strptime('2019/12/11-12:11:00.810', manohist_ingester.EPOCH_FORMAT),
263        epoch=datetime(2022,7,6,15,0,0,901000),
264        acc_comp_1=-0.0,
265        acc_comp_2=0.16640648E-04,
266        acc_comp_3=0.0,
267        flag=0)
268
269    # decode file
270    ENTRY_COUNT = 26
271    actual_results = list(manohist_ingester.parse_manoeuvres(AUX_PRODUCT_DIR.joinpath(MANOHIST_FILE)))
272
273    assert ENTRY_COUNT == len(actual_results)
274    assert actual_results[0] == expected_result_1st
275    print_out("MANOHIST decoder test passed for first result: {}", expected_result_1st)
276    assert actual_results[ENTRY_COUNT-1] == expected_result_last
277    print_out("MANOHIST decoder test passed for last result: {}", expected_result_last)
278
279
280def test_MANOPREDIC_decoder():
281    """Decoder test for MANOPREDIC aux files.
282    Compare product file decoding against expected tuple values """
283    from chartepssg.alg import manopredic_ingester
284
285    # From visual inspection we have the followwing first and only value
286    # First burn     2019/12/11-12:03:58.533    2.091 m/s OOP  OCM   17.402 deg
287    expected_result = manopredic_ingester.Manoeuvre(
288        #sid=SCID_TO_SID_MAP['S6A'],
289        # datetime.strptime('2019/12/11-12:03:58.533', manopredic_ingester.EXEC_TIME_FORMAT),
290
291        file_gen_time=datetime(2022,6,15,12,31,54,235000),
292        optim_time=datetime(2022,6,15,12,31,6,642000),
293        exec_time=datetime(2022,6,22,15,0,0,0),
294        mode='INP  OCM',
295        size=-0.05,
296        pso=231.145)
297
298    # decode file
299    actual_results = list(manopredic_ingester.parse_manoeuvres(AUX_PRODUCT_DIR.joinpath(MANOPREDIC_FILE)))
300
301    compare(actual_results[0], expected_result)
302    # assert actual_results[0] == expected_result
303    print_out("MANOPREDIC decoder test passed for result: {}", expected_result)