23
23
'async' : "vires_fetch_filtered_data_async.xml" ,
24
24
'model_info' : "vires_get_model_info.xml" ,
25
25
'times_from_orbits' : "vires_times_from_orbits.xml" ,
26
- 'get_observatories' : 'vires_get_observatories.xml'
26
+ 'get_observatories' : 'vires_get_observatories.xml' ,
27
+ 'get_conjunctions' : 'vires_get_conjunctions.xml' ,
27
28
}
28
29
29
30
REFERENCES = {
@@ -401,8 +402,6 @@ class SwarmRequest(ClientRequest):
401
402
402
403
Args:
403
404
url (str):
404
- username (str):
405
- password (str):
406
405
token (str):
407
406
config (str or ClientConfig):
408
407
logging_level (str):
@@ -415,6 +414,10 @@ class SwarmRequest(ClientRequest):
415
414
'CryoSat-2' : None ,
416
415
}
417
416
417
+ CONJUNCTION_MISISON_SPACECRAFT_PAIRS = {
418
+ (('Swarm' , 'A' ), ('Swarm' , 'B' )),
419
+ }
420
+
418
421
COLLECTIONS = {
419
422
"MAG" : ["SW_OPER_MAG{}_LR_1B" .format (x ) for x in "ABC" ],
420
423
"MAG_HR" : ["SW_OPER_MAG{}_HR_1B" .format (x ) for x in "ABC" ],
@@ -728,7 +731,7 @@ class SwarmRequest(ClientRequest):
728
731
"B_FGM1" , "B_FGM2" , "B_FGM3" , "q_NEC_CRF" , "q_error" ,
729
732
],
730
733
"MAG_GRACE" : [
731
- "F" , "B_NEC" , "B_NEC_raw" , "B_FGM" , "B_mod_NEC" ,
734
+ "F" , "B_NEC" , "B_NEC_raw" , "B_FGM" ,
732
735
"q_NEC_CRF" , "q_error" ,
733
736
],
734
737
"MAG_GFO" : [
@@ -770,10 +773,10 @@ class SwarmRequest(ClientRequest):
770
773
"MCO_SHA_2X" , "CHAOS" , "CHAOS-MMA" , "MMA_SHA_2C" , "MMA_SHA_2F" , "MIO_SHA_2C" , "MIO_SHA_2D" , "SwarmCI" ,
771
774
]
772
775
773
- def __init__ (self , url = None , username = None , password = None , token = None ,
776
+ def __init__ (self , url = None , token = None ,
774
777
config = None , logging_level = "NO_LOGGING" ):
775
778
super ().__init__ (
776
- url , username , password , token , config , logging_level ,
779
+ url , token , config , logging_level ,
777
780
server_type = "Swarm"
778
781
)
779
782
@@ -1309,16 +1312,38 @@ def get_times_for_orbits(self, start_orbit, end_orbit, mission="Swarm", spacecra
1309
1312
start_orbit = int (start_orbit )
1310
1313
end_orbit = int (end_orbit )
1311
1314
1312
- if mission not in self .MISSION_SPACECRAFTS :
1313
- raise ValueError (
1314
- f"Invalid mission { mission } !"
1315
- f"Allowed options are: { ',' .join (self .MISSION_SPACECRAFTS )} "
1316
- )
1315
+ # Change to spacecraft = "A" etc. for this request
1316
+ spacecraft = self ._fix_spacecraft (mission , spacecraft )
1317
+ self ._check_mission_spacecraft (mission , spacecraft )
1318
+
1319
+ templatefile = TEMPLATE_FILES ["times_from_orbits" ]
1320
+ template = JINJA2_ENVIRONMENT .get_template (templatefile )
1321
+ request = template .render (
1322
+ mission = mission ,
1323
+ spacecraft = spacecraft ,
1324
+ start_orbit = start_orbit ,
1325
+ end_orbit = end_orbit
1326
+ ).encode ('UTF-8' )
1327
+ response = self ._get (
1328
+ request , asynchronous = False , show_progress = False )
1329
+ responsedict = json .loads (response .decode ('UTF-8' ))
1330
+ start_time = parse_datetime (responsedict ['start_time' ])
1331
+ end_time = parse_datetime (responsedict ['end_time' ])
1332
+ return start_time , end_time
1317
1333
1334
+ def _fix_spacecraft (self , mission , spacecraft ):
1318
1335
# Change to spacecraft = "A" etc. for this request
1319
1336
spacecraft = str (spacecraft ) if spacecraft is not None else None
1320
1337
if mission == "Swarm" and spacecraft in ("Alpha" , "Bravo" , "Charlie" ):
1321
1338
spacecraft = spacecraft [0 ]
1339
+ return spacecraft
1340
+
1341
+ def _check_mission_spacecraft (self , mission , spacecraft ):
1342
+ if mission not in self .MISSION_SPACECRAFTS :
1343
+ raise ValueError (
1344
+ f"Invalid mission { mission } !"
1345
+ f"Allowed options are: { ',' .join (self .MISSION_SPACECRAFTS )} "
1346
+ )
1322
1347
1323
1348
if self .MISSION_SPACECRAFTS [mission ]:
1324
1349
# missions with required spacecraft id
@@ -1339,20 +1364,6 @@ def get_times_for_orbits(self, start_orbit, end_orbit, mission="Swarm", spacecra
1339
1364
"Set spacecraft to None."
1340
1365
)
1341
1366
1342
- templatefile = TEMPLATE_FILES ["times_from_orbits" ]
1343
- template = JINJA2_ENVIRONMENT .get_template (templatefile )
1344
- request = template .render (
1345
- mission = mission ,
1346
- spacecraft = spacecraft ,
1347
- start_orbit = start_orbit ,
1348
- end_orbit = end_orbit
1349
- ).encode ('UTF-8' )
1350
- response = self ._get (
1351
- request , asynchronous = False , show_progress = False )
1352
- responsedict = json .loads (response .decode ('UTF-8' ))
1353
- start_time = parse_datetime (responsedict ['start_time' ])
1354
- end_time = parse_datetime (responsedict ['end_time' ])
1355
- return start_time , end_time
1356
1367
1357
1368
def get_orbit_number (self , spacecraft , input_time , mission = "Swarm" ):
1358
1369
"""Translate a time to an orbit number.
@@ -1506,3 +1517,89 @@ def _check_deprecated_models(models):
1506
1517
print ("WARNING: Model {} is deprecated. {}" .format (
1507
1518
deprecated_model , DEPRECATED_MODELS [deprecated_model ]
1508
1519
), file = sys .stdout )
1520
+
1521
+
1522
+ def get_conjunctions (self , start_time = None , end_time = None , threshold = 1.0 ,
1523
+ spacecraft1 = 'A' , spacecraft2 = 'B' ,
1524
+ mission1 = 'Swarm' , mission2 = 'Swarm' ):
1525
+ """ Get times of the spacecraft conjunctions. Currently available for
1526
+ the following spacecraft pairs:
1527
+ - Swarm-A/Swarm-B
1528
+
1529
+ Args:
1530
+ start_time (datetime / ISO_8601 string): optional start time
1531
+ end_time (datetime / ISO_8601 string): optional end time
1532
+ threshold (float): optional maximum allowed angular separation
1533
+ in degrees; by default set to 1; allowed values are [0, 180]
1534
+ spacecraft1: identifier of the first spacecraft, default to 'A'
1535
+ spacecraft2: identifier of the second spacecraft, default to 'B'
1536
+ mission1 (str): mission of the first spacecraft, defaults to 'Swarm'
1537
+ mission2 (str): mission of the first spacecraft, defaults to 'Swarm'
1538
+
1539
+ Returns:
1540
+ ReturnedData:
1541
+ """
1542
+ try :
1543
+ start_time = parse_datetime (start_time ) if start_time else None
1544
+ end_time = parse_datetime (end_time ) if end_time else None
1545
+ except TypeError :
1546
+ raise TypeError (
1547
+ "start_time and end_time must be datetime objects or ISO-8601 "
1548
+ "date/time strings"
1549
+ ) from None
1550
+
1551
+ if not (0 <= threshold <= 180 ):
1552
+ raise ValueError ("Invalid threshold value!" )
1553
+
1554
+ spacecraft1 = self ._fix_spacecraft (mission1 , spacecraft1 )
1555
+ spacecraft2 = self ._fix_spacecraft (mission2 , spacecraft2 )
1556
+
1557
+ self ._check_mission_spacecraft (mission1 , spacecraft1 )
1558
+ self ._check_mission_spacecraft (mission2 , spacecraft2 )
1559
+
1560
+ if (mission1 , spacecraft1 ) == (mission2 , spacecraft2 ):
1561
+ raise ValueError (
1562
+ "The first and second spacecraft must not be the same!"
1563
+ )
1564
+
1565
+ spacecraft_pair = tuple (sorted ([
1566
+ (mission1 , spacecraft1 ), (mission2 , spacecraft2 )
1567
+ ]))
1568
+
1569
+ if spacecraft_pair not in self .CONJUNCTION_MISISON_SPACECRAFT_PAIRS :
1570
+ raise ValueError (
1571
+ "Conjunctions not available for the requested "
1572
+ "spacecraft pair {spacecraft_pair}!"
1573
+ )
1574
+
1575
+ templatefile = TEMPLATE_FILES ["get_conjunctions" ]
1576
+ template = JINJA2_ENVIRONMENT .get_template (templatefile )
1577
+ request = template .render (
1578
+ begin_time = start_time ,
1579
+ end_time = end_time ,
1580
+ spacecraft1 = spacecraft1 ,
1581
+ spacecraft2 = spacecraft2 ,
1582
+ mission1 = mission1 ,
1583
+ mission2 = mission2 ,
1584
+ threshold = threshold ,
1585
+ ).encode ('UTF-8' )
1586
+
1587
+ show_progress = False
1588
+ leave_progress_bar = False
1589
+ response = ReturnedDataFile (filetype = "cdf" )
1590
+
1591
+ response_handler = self ._response_handler (
1592
+ retdatafile = response ,
1593
+ show_progress = show_progress ,
1594
+ leave_progress_bar = leave_progress_bar ,
1595
+ )
1596
+
1597
+ self ._get (
1598
+ request = request ,
1599
+ asynchronous = False ,
1600
+ show_progress = show_progress ,
1601
+ leave_progress_bar = leave_progress_bar ,
1602
+ response_handler = response_handler ,
1603
+ )
1604
+
1605
+ return response
0 commit comments