def ion_dist_single(probe, year, doy, hour, minute, second, remove_advect=False): """ Read in ion distribution function. Parameters ---------- probe : int, string Helios probe to import data from. Must be 1 or 2. year : int Year doy : int Day of year hour : int Hour minute : int Minute. second : int Second remove_advect : bool, optional If *False*, the distribution is returned in the spacecraft frame. If *True*, the distribution is returned in the solar wind frame, by subtracting the spacecraft velocity from the velcoity of each bin. Note this significantly slows down reading in the distribution. Returns ------- dist : DataFrame 3D ion distribution function """ probe = _check_probe(probe) f, filename = _loaddistfile(probe, year, doy, hour, minute, second) nionlines = None # Number of lines in ion distribution linesread = 0 # Stores the total number of lines read in the file # Loop through file to find end of ion distribution function for i, line in enumerate(f): # Find start of proton distribution function if line[0:23] == 'Maximum of distribution': ionstartline = i + 1 # Find number of lines in ion distribution function if line[0:4] == ' 2-D': nionlines = i - ionstartline break linesread += i # Bizzare case where there are two proton distributions in one file, # or there's no electron data available for i, line in enumerate(f): if line[0:23] == 'Maximum of distribution' or\ line[0:30] == ' 1.2 Degree, Pizzo correction' or\ line[0:30] == ' -1.2 Degree, Pizzo correction': warnings.warn("More than one ion distribution function found", RuntimeWarning) # NOTE: Bodge linesread -= 1 break f.close() # If there's no electron data to get number of lines, set end of ion # distribution function to end of file if nionlines is None: nionlines = i - ionstartline + 1 ##################################### # Read and process ion distribution # ##################################### # If no ion data in file if nionlines < 1: raise RuntimeError('No ion distribution function data in file') # Arguments for reading in data readargs = { 'usecols': [0, 1, 2, 3, 4, 5, 6, 7], 'names': ['Az', 'El', 'E_bin', 'pdf', 'counts', 'vx', 'vy', 'vz'], 'delim_whitespace': True, 'skiprows': ionstartline, 'nrows': nionlines } # Read in data dist = pd.read_table(filename, **readargs) # Remove spacecraft abberation # Assumes that spacecraft motion is always in the ecliptic (x-y) # plane if remove_advect: params = distparams_single(probe, year, doy, hour, minute, second) dist['vx'] += params['helios_vr'] dist['vy'] += params['helios_v'] # Convert to SI units dist[['vx', 'vy', 'vz']] *= 1e3 dist['pdf'] *= 1e12 # Calculate magnitude, elevation and azimuth of energy bins dist['|v|'], dist['theta'], dist['phi'] =\ util._cart2sph(dist['vx'], dist['vy'], dist['vz']) # Calculate bin energy assuming particles are protons dist['E_proton'] = 0.5 * constants.m_p.value * ((dist['|v|'])**2) # Convert to multi-index using azimuth, elevation, and energy bins dist = dist.set_index(['E_bin', 'El', 'Az']) return dist
def electron_dist_single(probe, year, doy, hour, minute, second, remove_advect=False): """ Read in 2D electron distribution function. Parameters ---------- probe : int, string Helios probe to import data from. Must be 1 or 2. year : int Year doy : int Day of year hour : int Hour. minute : int Minute second : int Second remove_advect : bool, optional If ``False``, the distribution is returned in the spacecraft frame. If ``True``, the distribution is returned in the solar wind frame, by subtracting the spacecraft velocity from the velcoity of each bin. Note this significantly slows down reading in the distribution. Returns ------- dist : DataFrame 2D electron distribution function """ probe = _check_probe(probe) f, filename = _loaddistfile(probe, year, doy, hour, minute, second) startline = None for i, line in enumerate(f): # Find start of electron distribution function if line[0:4] == ' 2-D': startline = i + 2 # Throw away next line (just has max of distribution) f.readline() # Throw away next line (just has table headings) if f.readline()[0:27] == ' no electron data available': return None break nlines = None for i, line in enumerate(f): if 'Degree, Pizzo correction' in line: break nlines = i + 1 if startline is None: return None ########################################## # Read and process electron distribution # ########################################## # Arguments for reading in data readargs = { 'usecols': [0, 1, 2, 3, 4, 5], 'names': ['Az', 'E_bin', 'pdf', 'counts', 'vx', 'vy'], 'delim_whitespace': True, 'skiprows': startline, 'nrows': nlines } # Read in data dist = pd.read_table(filename, **readargs) if dist.empty: return None # Remove spacecraft abberation # Assumes that spacecraft motion is always in the ecliptic (x-y) # plane if remove_advect: params = distparams_single(probe, year, doy, hour, minute, second) dist['vx'] += params['helios_vr'] dist['vy'] += params['helios_v'] # Convert to SI units dist[['vx', 'vy']] *= 1e3 dist['pdf'] *= 1e12 # Calculate spherical coordinates of energy bins dist['|v|'], _, dist['phi'] =\ util._cart2sph(dist['vx'], dist['vy'], 0) # Calculate bin energy assuming particles are electrons dist['E_electron'] = 0.5 * constants.m_e.value *\ ((dist['|v|']) ** 2) # Convert to multi-index using Azimuth and energy bin dist = dist.set_index(['E_bin', 'Az']) f.close() return dist