@@ -905,10 +905,10 @@ def __init__(self, **kwargs):
905
905
906
906
@classmethod
907
907
def load_ascii_catalogs (cls , filename , ** kwargs ):
908
- """ Loads multiple CSEP catalogs in ASCII format.
908
+ """ Loads multiple catalogs in csep-ascii format.
909
909
910
- This function can load multiple catalogs stored in a single file or directories . This typically called to
911
- load a catalog-based forecast.
910
+ This function can load multiple catalogs stored in a single file. This typically called to
911
+ load a catalog-based forecast, but could also load a collection of catalogs stored in the same file
912
912
913
913
Args:
914
914
filename (str): filepath or directory of catalog files
@@ -926,15 +926,46 @@ def parse_filename(filename):
926
926
start_time = strptime_to_utc_datetime (split_fname [1 ], format = "%Y-%m-%dT%H-%M-%S-%f" )
927
927
return (name , start_time )
928
928
929
+ def read_float (val ):
930
+ """Returns val as float or None if unable"""
931
+ try :
932
+ val = float (val )
933
+ except :
934
+ val = None
935
+ return val
936
+
929
937
def is_header_line (line ):
930
- if line [0 ] == 'lon' :
938
+ if line [0 ]. lower () == 'lon' :
931
939
return True
932
940
else :
933
941
return False
934
942
935
- name_from_file , start_time = parse_filename (filename )
943
+ def read_catalog_line (line ):
944
+ # convert to correct types
945
+ lon = read_float (line [0 ])
946
+ lat = read_float (line [1 ])
947
+ magnitude = read_float (line [2 ])
948
+ # maybe fractional seconds are not included
949
+ origin_time = line [3 ]
950
+ if origin_time :
951
+ try :
952
+ origin_time = strptime_to_utc_epoch (line [3 ], format = '%Y-%m-%dT%H:%M:%S.%f' )
953
+ except ValueError :
954
+ origin_time = strptime_to_utc_epoch (line [3 ], format = '%Y-%m-%dT%H:%M:%S' )
955
+ depth = read_float (line [4 ])
956
+ catalog_id = int (line [5 ])
957
+ event_id = line [6 ]
958
+ # temporary event
959
+ temp_event = (event_id , origin_time , lat , lon , depth , magnitude )
960
+ return temp_event , catalog_id
961
+
936
962
# overwrite filename, if user specifies
937
- kwargs .setdefault ('name' , name_from_file )
963
+ try :
964
+ name_from_file , start_time = parse_filename (filename )
965
+ kwargs .setdefault ('name' , name_from_file )
966
+ except :
967
+ pass
968
+
938
969
# handle all catalogs in single file
939
970
if os .path .isfile (filename ):
940
971
with open (filename , 'r' , newline = '' ) as input_file :
@@ -948,52 +979,53 @@ def is_header_line(line):
948
979
if prev_id is None :
949
980
if is_header_line (line ):
950
981
continue
951
- # convert to correct types
952
- lon = float (line [0 ])
953
- lat = float (line [1 ])
954
- magnitude = float (line [2 ])
955
- # maybe fractional seconds are not included
956
- try :
957
- origin_time = strptime_to_utc_epoch (line [3 ], format = '%Y-%m-%dT%H:%M:%S.%f' )
958
- except ValueError :
959
- origin_time = strptime_to_utc_epoch (line [3 ], format = '%Y-%m-%dT%H:%M:%S' )
960
- depth = float (line [4 ])
961
- catalog_id = int (line [5 ])
962
- event_id = line [6 ]
982
+ # read line and return catalog id
983
+ temp_event , catalog_id = read_catalog_line (line )
984
+ empty = False
985
+ # OK if event_id is empty
986
+ if all ([val in (None , '' ) for val in temp_event [1 :]]):
987
+ empty = True
963
988
# first event is when prev_id is none, catalog_id should always start at zero
964
989
if prev_id is None :
965
990
prev_id = 0
966
991
# if the first catalog doesn't start at zero
967
992
if catalog_id != prev_id :
968
- prev_id = catalog_id
969
- # store this event for next time
970
- events = [(event_id , origin_time , lat , lon , depth , magnitude )]
993
+ if not empty :
994
+ events = [temp_event ]
995
+ else :
996
+ events = []
971
997
for id in range (catalog_id ):
972
998
yield cls (data = [], catalog_id = id , ** kwargs )
973
- # deal with cases of events
999
+ prev_id = catalog_id
1000
+ continue
1001
+ # accumulate event if catalog_id is the same as previous event
974
1002
if catalog_id == prev_id :
1003
+ if not all ([val in (None , '' ) for val in temp_event ]):
1004
+ events .append (temp_event )
975
1005
prev_id = catalog_id
976
- events .append ((event_id , origin_time , lat , lon , depth , magnitude ))
977
1006
# create and yield class if the events are from different catalogs
978
1007
elif catalog_id == prev_id + 1 :
979
- catalog = cls (data = events , catalog_id = prev_id , ** kwargs )
1008
+ yield cls (data = events , catalog_id = prev_id , ** kwargs )
1009
+ # add event to new event list
1010
+ if not empty :
1011
+ events = [temp_event ]
1012
+ else :
1013
+ events = []
980
1014
prev_id = catalog_id
981
- # add first event to new event list
982
- events = [(event_id , origin_time , lat , lon , depth , magnitude )]
983
- yield catalog
984
1015
# this implies there are empty catalogs, because they are not listed in the ascii file
985
1016
elif catalog_id > prev_id + 1 :
986
- catalog = cls (data = events , catalog_id = prev_id , ** kwargs )
987
- # add event to new event list
988
- events = [(event_id , origin_time , lat , lon , depth , magnitude )]
1017
+ yield cls (data = events , catalog_id = prev_id , ** kwargs )
989
1018
# if prev_id = 0 and catalog_id = 2, then we skipped one catalog. thus, we skip catalog_id - prev_id - 1 catalogs
990
1019
num_empty_catalogs = catalog_id - prev_id - 1
991
- # create empty catalog classes
1020
+ # first yield empty catalog classes
992
1021
for id in range (num_empty_catalogs ):
993
1022
yield cls (data = [], catalog_id = catalog_id - num_empty_catalogs + id , ** kwargs )
994
- # finally we want to yield the buffered catalog to preserve order
995
1023
prev_id = catalog_id
996
- yield catalog
1024
+ # add event to new event list
1025
+ if not empty :
1026
+ events = [temp_event ]
1027
+ else :
1028
+ events = []
997
1029
else :
998
1030
raise ValueError (
999
1031
"catalog_id should be monotonically increasing and events should be ordered by catalog_id" )
0 commit comments