1818_log = logging .getLogger (__name__ )
1919
2020
21- def convert_to_OG1 (list_of_datasets : list [xr .Dataset ] | xr .Dataset , contrib_to_append : dict [str , str ] | None = None ,) -> tuple [xr .Dataset , list [str ]]:
21+ def convert_to_OG1 (
22+ list_of_datasets : list [xr .Dataset ] | xr .Dataset ,
23+ contrib_to_append : dict [str , str ] | None = None ,
24+ ) -> tuple [xr .Dataset , list [str ]]:
2225 """Convert Seaglider basestation datasets to OG1 format.
2326 Processes a list of xarray datasets or a single xarray dataset, converts them to OG1 format,
2427 concatenates the datasets, sorts by time, and applies attributes. Main conversion function that
@@ -64,6 +67,8 @@ def convert_to_OG1(list_of_datasets: list[xr.Dataset] | xr.Dataset, contrib_to_a
6467
6568 ds_og1 = xr .concat (processed_datasets , dim = "N_MEASUREMENTS" )
6669 ds_og1 = ds_og1 .sortby ("TIME" )
70+ # Change format of time into datetime64[ns] to avoid problems with attributes and writing to netcdf
71+ ds_og1 ["TIME" ] = (ds_og1 ["TIME" ].astype ("float64" ) * 1e9 ).astype ("datetime64[ns]" )
6772
6873 # Apply attributes
6974 ordered_attributes = update_dataset_attributes (
@@ -104,12 +109,18 @@ def convert_to_OG1(list_of_datasets: list[xr.Dataset] | xr.Dataset, contrib_to_a
104109 ds_og1 ["TRAJECTORY" ].attrs ["long_name" ] = "trajectory name"
105110 ds_og1 ["TRAJECTORY" ].attrs ["cf_role" ] = "trajectory_id"
106111
107- ds_og1 ["DEPLOYMENT_LATITUDE" ] = xr .DataArray (ds_og1 .LATITUDE .values [~ np .isnan (ds_og1 .LATITUDE )][0 ],
108- attrs = {"long_name" : "latitude of deployment" })
109- ds_og1 ["DEPLOYMENT_LONGITUDE" ] = xr .DataArray (ds_og1 .LONGITUDE .values [~ np .isnan (ds_og1 .LONGITUDE )][0 ],
110- attrs = {"long_name" : "longitude of deployment" })
111- ds_og1 ["DEPLOYMENT_TIME" ] = xr .DataArray (ds_og1 .TIME .values [~ np .isnan (ds_og1 .TIME )][0 ],
112- attrs = {"long_name" : "time of deployment" })
112+ ds_og1 ["DEPLOYMENT_LATITUDE" ] = xr .DataArray (
113+ ds_og1 .LATITUDE .values [~ np .isnan (ds_og1 .LATITUDE )][0 ],
114+ attrs = {"long_name" : "latitude of deployment" },
115+ )
116+ ds_og1 ["DEPLOYMENT_LONGITUDE" ] = xr .DataArray (
117+ ds_og1 .LONGITUDE .values [~ np .isnan (ds_og1 .LONGITUDE )][0 ],
118+ attrs = {"long_name" : "longitude of deployment" },
119+ )
120+ ds_og1 ["DEPLOYMENT_TIME" ] = xr .DataArray (
121+ ds_og1 .TIME .values [~ np .isnan (ds_og1 .TIME )][0 ],
122+ attrs = {"long_name" : "time of deployment" },
123+ )
113124
114125 # Remove attributes from TIME_GPS
115126 if "TIME_GPS" in ds_og1 .variables :
@@ -274,8 +285,10 @@ def process_dataset(ds1_base: xr.Dataset, firstrun: bool = False) -> tuple[
274285 ds_new = tools .add_sensor_to_dataset (ds_new , ds_sensor , ds_sgcal , firstrun )
275286
276287 # To avoid problems, reset the dtype of TIME_GPS
277- ds_new ['TIME_GPS' ] = ds_new ['TIME_GPS' ].astype ('datetime64[ns]' )
278- vars_to_remove = vocabularies .vars_to_remove #+ ["TIME_GPS"]
288+ ds_new ["TIME_GPS" ] = (ds_new ["TIME_GPS" ].astype ("float64" ) * 1e9 ).astype (
289+ "datetime64[ns]"
290+ )
291+ vars_to_remove = vocabularies .vars_to_remove # + ["TIME_GPS"]
279292 vars_present_to_remove = [var for var in vars_to_remove if var in ds_new .variables ]
280293
281294 # Drop them
@@ -288,6 +301,7 @@ def process_dataset(ds1_base: xr.Dataset, firstrun: bool = False) -> tuple[
288301 attr_warnings = ""
289302 return ds_new , attr_warnings , ds_sgcal , ds_other , ds_log
290303
304+
291305def standardise_OG10 (
292306 ds : xr .Dataset ,
293307 firstrun : bool = False ,
@@ -367,7 +381,10 @@ def standardise_OG10(
367381 )
368382 ### Only log a warning for variables that aren't in the vocabularies and aren't in the list of variables to keep or remove
369383 ### Removed varaiables will be printed in the log as being removed, so no need to log a warning for them here.
370- if orig_varname not in (* vocabularies .vars_as_is , * vocabularies .vars_to_remove ):
384+ if orig_varname not in (
385+ * vocabularies .vars_as_is ,
386+ * vocabularies .vars_to_remove ,
387+ ):
371388 vars_not_in_vocab .append (orig_varname )
372389
373390 if firstrun and vars_not_in_vocab :
@@ -505,7 +522,9 @@ def add_gps_info_to_dataset(ds: xr.Dataset, gps_ds: xr.Dataset) -> xr.Dataset:
505522##-----------------------------------------------------------------------------------------
506523## Editing attributes
507524##-----------------------------------------------------------------------------------------
508- def update_dataset_attributes (ds : xr .Dataset , contrib_to_append : dict [str , str ] | None ) -> dict [str , str ]:
525+ def update_dataset_attributes (
526+ ds : xr .Dataset , contrib_to_append : dict [str , str ] | None
527+ ) -> dict [str , str ]:
509528 """Update the attributes of the dataset based on the provided attribute input.
510529
511530 Processes contributor information, time attributes, and applies OG1
@@ -570,7 +589,9 @@ def update_dataset_attributes(ds: xr.Dataset, contrib_to_append: dict[str, str]
570589 return ordered_attributes
571590
572591
573- def get_contributors (ds : xr .Dataset , values_to_append : dict [str , str ] | None = None ) -> dict [str , str ]:
592+ def get_contributors (
593+ ds : xr .Dataset , values_to_append : dict [str , str ] | None = None
594+ ) -> dict [str , str ]:
574595 """Extract and format contributor information for OG1 attributes.
575596
576597 Processes creator and contributor information from dataset attributes,
@@ -589,6 +610,7 @@ def get_contributors(ds: xr.Dataset, values_to_append: dict[str, str] | None = N
589610 Dictionary with formatted contributor attribute strings.
590611
591612 """
613+
592614 # Function to create or append to a list
593615 def create_or_append_list (existing_list , new_item ):
594616 if new_item not in existing_list :
@@ -808,7 +830,9 @@ def get_time_attributes(ds: xr.Dataset) -> dict[str, str]:
808830 return time_attrs
809831
810832
811- def extract_attr_to_keep (ds1 : xr .Dataset , attr_as_is : list [str ] = vocabularies .global_attrs ["attr_as_is" ]) -> dict [str , str ]:
833+ def extract_attr_to_keep (
834+ ds1 : xr .Dataset , attr_as_is : list [str ] = vocabularies .global_attrs ["attr_as_is" ]
835+ ) -> dict [str , str ]:
812836 """Extract attributes to retain unchanged.
813837
814838 Parameters
@@ -835,7 +859,8 @@ def extract_attr_to_keep(ds1: xr.Dataset, attr_as_is: list[str] = vocabularies.g
835859
836860
837861def extract_attr_to_rename (
838- ds1 : xr .Dataset , attr_to_rename : dict [str , str ] = vocabularies .global_attrs ["attr_to_rename" ]
862+ ds1 : xr .Dataset ,
863+ attr_to_rename : dict [str , str ] = vocabularies .global_attrs ["attr_to_rename" ],
839864) -> dict [str , str ]:
840865 """Extract and rename attributes according to OG1 vocabulary.
841866
@@ -861,7 +886,12 @@ def extract_attr_to_rename(
861886 return renamed_attrs
862887
863888
864- def process_and_save_data (input_location : str , save : bool = False , output_dir : str = "." , run_quietly : bool = True ) -> xr .Dataset :
889+ def process_and_save_data (
890+ input_location : str ,
891+ save : bool = False ,
892+ output_dir : str = "." ,
893+ run_quietly : bool = True ,
894+ ) -> xr .Dataset :
865895 """Process and save data from the specified input location.
866896
867897 This function loads and concatenates datasets from the server, converts them to OG1 format,
0 commit comments