def read_cdf(fname): """ Read a CDF file that follows the ISTP/IACG guidelines. Parameters ---------- fname : path-like Location of single CDF file to read. Returns ------- list[GenericTimeSeries] A list of time series objects, one for each unique time index within the CDF file. References ---------- Space Physics Guidelines for CDF https://spdf.gsfc.nasa.gov/sp_use_of_cdf.html """ cdf = cdflib.CDF(str(fname)) # Extract the time varying variables cdf_info = cdf.cdf_info() meta = cdf.globalattsget() all_var_keys = cdf_info['rVariables'] + cdf_info['zVariables'] var_attrs = {key: cdf.varattsget(key) for key in all_var_keys} # Get keys that depend on time var_keys = [var for var in var_attrs if 'DEPEND_0' in var_attrs[var]] # Get unique time index keys time_index_keys = sorted(set([var_attrs[var]['DEPEND_0'] for var in var_keys])) all_ts = [] # For each time index, construct a GenericTimeSeries for index_key in time_index_keys: try: index = cdf.varget(index_key) except ValueError: # Empty index for cdflib >= 0.3.20 continue if index is None: # Empty index for cdflib <0.3.20 continue # TODO: use to_astropy_time() instead here when we drop pandas in timeseries index = CDFepoch.to_datetime(index) df = pd.DataFrame(index=pd.DatetimeIndex(name=index_key, data=index)) units = {} for var_key in sorted(var_keys): attrs = var_attrs[var_key] if attrs['DEPEND_0'] != index_key: continue # Get data if cdf.varinq(var_key)['Last_Rec'] == -1: log.debug(f'Skipping {var_key} in {fname} as it has zero elements') continue data = cdf.varget(var_key) # Get units if 'UNITS' in attrs: unit_str = attrs['UNITS'] try: unit = u.Unit(unit_str) except ValueError: if unit_str in _known_units: unit = _known_units[unit_str] else: warn_user(f'astropy did not recognize units of "{unit_str}". ' 'Assigning dimensionless units. ' 'If you think this unit should not be dimensionless, ' 'please raise an issue at https://github.com/sunpy/sunpy/issues') unit = u.dimensionless_unscaled else: warn_user(f'No units provided for variable "{var_key}". ' 'Assigning dimensionless units.') unit = u.dimensionless_unscaled if data.ndim == 2: # Multiple columns, give each column a unique label for i, col in enumerate(data.T): df[var_key + f'_{i}'] = col units[var_key + f'_{i}'] = unit else: # Single column df[var_key] = data units[var_key] = unit all_ts.append(GenericTimeSeries(data=df, units=units, meta=meta)) if not len(all_ts): log.debug(f'No data found in file {fname}') return all_ts
def time_epoch_to_datetime_tt2000(self, to_np): cdfepoch.to_datetime(self.epochs_tt2000)
def _convert_cdf_time_types(data, atts, properties, to_datetime=False, to_unixtime=False): ''' # Converts CDF time types into either datetime objects, unixtime, or nothing # If nothing, ALL CDF_EPOCH16 types are converted to CDF_EPOCH, because xarray can't handle int64s ''' if not hasattr(data, '__len__'): data = [data] if to_datetime and to_unixtime: print( "Cannot convert to both unixtime and datetime. Continuing with conversion to unixtime." ) to_datetime = False # Convert all data in the "data" variable to unixtime or datetime if needed data_type = properties['Data_Type_Description'] if len(data) == 0 or data_type not in ('CDF_EPOCH', 'CDF_EPOCH16', 'CDF_TIME_TT2000'): new_data = data else: if to_datetime: new_data = cdfepoch.to_datetime(data) if 'UNITS' in atts: atts['UNITS']['Data'] = 'Datetime (UTC)' elif to_unixtime: new_data = cdfepoch.unixtime(data) if 'UNITS' in atts: atts['UNITS']['Data'] = 'seconds' else: if data_type == 'CDF_EPOCH16': new_data = cdfepoch.compute(cdfepoch.breakdown(data)[0:7]) else: new_data = data # Convert all the attributes in the "atts" dictionary to unixtime or datetime if needed new_atts = {} for att in atts: data_type = atts[att]['Data_Type'] data = atts[att]['Data'] if not hasattr(data, '__len__'): data = [data] if len(data) == 0 or data_type not in ('CDF_EPOCH', 'CDF_EPOCH16', 'CDF_TIME_TT2000'): new_atts[att] = data else: if to_datetime: new_atts[att] = cdfepoch.to_datetime(data) elif to_unixtime: new_atts[att] = cdfepoch.unixtime(data) else: if data_type == 'CDF_EPOCH16': new_atts[att] = cdfepoch.compute( cdfepoch.breakdown(data)[0:7]) else: new_atts[att] = data return new_data, new_atts
def time_epoch_to_datetime(self, to_np): cdfepoch.to_datetime(self.epochs)
def read_cdf(fname): """ Read a CDF file that follows the ISTP/IACG guidelines. Parameters ---------- fname : path-like Location of single CDF file to read. Returns ------- list[GenericTimeSeries] A list of time series objects, one for each unique time index within the CDF file. References ---------- Space Physics Guidelines for CDF https://spdf.gsfc.nasa.gov/sp_use_of_cdf.html """ cdf = cdflib.CDF(str(fname)) # Extract the time varying variables cdf_info = cdf.cdf_info() meta = cdf.globalattsget() all_var_keys = cdf_info['rVariables'] + cdf_info['zVariables'] var_attrs = {key: cdf.varattsget(key) for key in all_var_keys} # Get keys that depend on time var_keys = [var for var in var_attrs if 'DEPEND_0' in var_attrs[var]] # Get unique time index keys time_index_keys = sorted( set([var_attrs[var]['DEPEND_0'] for var in var_keys])) all_ts = [] # For each time index, construct a GenericTimeSeries for index_key in time_index_keys: index = cdf.varget(index_key) # TODO: use to_astropy_time() instead here when we drop pandas in timeseries index = CDFepoch.to_datetime(index) df = pd.DataFrame(index=pd.DatetimeIndex(name=index_key, data=index)) units = {} for var_key in sorted(var_keys): attrs = var_attrs[var_key] if attrs['DEPEND_0'] != index_key: continue # Get data data = cdf.varget(var_key) # Get units unit = attrs['UNITS'] if unit in ['None', '', 'unitless']: unit = u.dimensionless_unscaled else: unit = u.Unit(unit) if data.ndim == 2: # Multiple columns, give each column a unique label for i, col in enumerate(data.T): df[var_key + f'_{i}'] = col units[var_key + f'_{i}'] = unit else: # Single column df[var_key] = data units[var_key] = unit all_ts.append(GenericTimeSeries(data=df, units=units, meta=meta)) return all_ts