Application Programming Interface
This library contains components for PyRayHF software.
- PyRayHF.library.azimuth_between_points(lon1_deg, lat1_deg, lon2_deg, lat2_deg)[source]
Compute forward azimuth from point 1 to point 2.
- Parameters:
- lon1_deg, lat1_degfloat or array-like
Longitude and latitude and of the starting point [degrees].
- lon2_deg, lat2_degfloat or array-like
Longitude and Latitude of the destination point [degrees].
- Returns:
- azimuth_degfloat or ndarray
Azimuth measured clockwise from geographic North [degrees], in the range [0, 360).
- PyRayHF.library.build_mup_function(mup_field: ndarray, x_grid: ndarray, z_grid: ndarray, *, geometry: str = 'cartesian', R_E: float = None, bounds_error: bool = False, fill_value: float = nan) Callable[[ndarray, ndarray], ndarray][source]
Construct callable for evaluating μ’(x, z) for group delay integration.
- Parameters:
- mup_fieldndarray
Grid of μ’ (group refractive index) values.
- x_gridndarray
- Horizontal coordinate grid:
For “cartesian”: horizontal distance [km].
For “spherical”: surface arc distance [km].
- z_gridndarray
Vertical coordinate grid [km].
- geometry{‘cartesian’, ‘spherical’}, optional
Coordinate system type. Default is ‘cartesian’.
- R_Efloat, optional
Earth radius [km], used only for spherical geometry.
- bounds_errorbool, optional
Passed to RegularGridInterpolator. If True, raise error outside grid.
- fill_valuefloat, optional
Fill value used for extrapolation. Default np.nan.
- Returns:
- mup_funccallable
Function mup_func(x, z) that evaluates μ’ at given coordinates.
Notes
For Cartesian geometry, (z, x) order is used in the interpolator.
- For Spherical geometry, (r, φ) order is used, where
r = R_E + z and φ = x / R_E.
- PyRayHF.library.build_refractive_index_interpolator_cartesian(z_grid: ndarray, x_grid: ndarray, n_field: ndarray, *, fill_value_n: float = nan, fill_value_grad: float = 0.0, bounds_error: bool = False, edge_order: int = 2) Callable[[ndarray, ndarray], Tuple[ndarray, ndarray, ndarray]][source]
Construct interpolators for refractive index n(z, x) and its gradients.
- Parameters:
- z_gridndarray, shape (nz,)
Altitude coordinates [km], strictly increasing.
- x_gridndarray, shape (nx,)
Horizontal coordinates [km], strictly increasing.
- n_fieldndarray, shape (nz, nx)
Refractive index values on (z, x) grid.
- fill_value_nfloat
Fill value for n outside grid (default NaN).
- fill_value_gradfloat
Fill value for gradients outside grid (default 0.0).
- bounds_errorbool
If True, raise error outside grid. If False, use fill values.
- edge_orderint
Accuracy order for finite differences (default 2).
- Returns:
- n_and_gradcallable
Function (x, z) → (n, dndx, dndz).
- PyRayHF.library.build_refractive_index_interpolator_spherical(z_grid: ndarray, x_grid: ndarray, n_field: ndarray, *, fill_value_n: float = nan, fill_value_grad: float = 0.0, bounds_error: bool = False, R_E: float = None, edge_order: int = 2) Callable[[ndarray, ndarray], Tuple[ndarray, ndarray, ndarray]][source]
Construct interpolators for refractive index μ(r, φ) and its gradients.
- Parameters:
- z_gridndarray, shape (nz,)
Altitude coordinates [km], strictly increasing.
- x_gridndarray, shape (nx,)
Horizontal coordinates [km], strictly increasing.
- n_fieldndarray, shape (nr, nφ)
Refractive index values on (r, φ) grid.
- fill_value_nfloat
Fill value for μ outside grid (default NaN).
- fill_value_gradfloat
Fill value for gradients outside grid (default 0.0).
- bounds_errorbool
If True, raise error outside grid. If False, use fill values.
- R_Eflt
Radius of the Earth (km).
- edge_orderint
Accuracy order for finite differences (default 2).
- Returns:
- n_and_grad_rphicallable
Function (φ, r) → (μ, ∂μ/∂r, ∂μ/∂φ).
- PyRayHF.library.calculate_gcd(lon0, lat0, lon1, lat1)[source]
Calculate great circle distance.
- Parameters:
- lon0array-like
value or np.array of longitudes of first position in degrees.
- lat0array-like
value or np.array of latitudes of first position in degrees.
- lon1array-like
value or np.array of longitudes of second position in degrees.
- lat1array-like
value or np.array of latitudes of second position in degrees.
- Returns:
- gcdarray-like
Great circle distance in degrees.
Notes
This function calculates great circle distance in degrees.
- PyRayHF.library.calculate_magnetic_field(year, month, day, lat, lon, aalt)[source]
Get magnetic field strength and angle from vertical.
- Parameters:
- year, month, dayint
Date at which to evaluate B field
- latarray-like
Latitude in degrees
- lonarray-like
Longitude in degrees
- aaltarray-like
Altitude array in km
- Returns:
- magarray-like
Magnetic field strength at each altitude [nT]
- psiarray-like
Magnetic field angle from vertical at each altitude [degrees]
Notes
This returns the total field strength and angle from vertical
- PyRayHF.library.constants()[source]
Define constants for virtual height calculation.
- Returns:
- cpfloat
Plasma frequency constant in Hz per sqrt(m^-3). f_p [Hz] = cp * sqrt(n_e [m^-3]).
- g_pfloat
Electron gyrofrequency constant in Hz/T (f_ce = g_p * B).
- R_Efloat
Earth radius [km].
- c_km_sfloat
Speed of light [km/s].
Notes
This function provides constants used in virtual height calculations.
- PyRayHF.library.den2freq(density)[source]
Convert plasma density to plasma frequency.
- Parameters:
- densityfloat or array-like
Plasma density in m^-3.
- Returns:
- frequencyfloat or array-like
Plasma frequency in Hz.
- PyRayHF.library.earth_radius_at_latitude(latitude)[source]
Calculate the radius of the Earth (in kilometers) for a given latitude.
- Parameters:
- latitudefloat
Geo Latitude in degrees.
- Returns:
- radiusfloat
Radius of the Earth in km.
- PyRayHF.library.eval_refractive_index_and_grad(x: ndarray, z: ndarray, n_interp: RegularGridInterpolator, dn_dx_interp: RegularGridInterpolator, dn_dz_interp: RegularGridInterpolator) Tuple[ndarray, ndarray, ndarray][source]
Evaluate refractive index and its gradients at (x, z).
- Parameters:
- xarray_like
Horizontal positions [km]. Scalar or array.
- zarray_like
Altitudes [km]. Scalar or array.
- n_interpRegularGridInterpolator
Interpolator for n(z, x).
- dn_dx_interpRegularGridInterpolator
Interpolator for ∂n/∂x(z, x).
- dn_dz_interpRegularGridInterpolator
Interpolator for ∂n/∂z(z, x).
- Returns:
- nnp.ndarray
Refractive index values at (x, z).
- dndxnp.ndarray
∂n/∂x [1/km] values at (x, z).
- dndznp.ndarray
∂n/∂z [1/km] values at (x, z).
Notes
Inputs x and z are broadcast to a common shape. Points are stacked as (z, x) before passing to interpolators. Output arrays match the broadcasted shape of inputs.
- PyRayHF.library.event_ground(s: float, y: ndarray, z_ground_km: float) float[source]
Stop when ray hits or goes below the ground.
- PyRayHF.library.event_x_left(s: float, y: ndarray, x_min_km: float) float[source]
Stop when ray exits left boundary.
- PyRayHF.library.event_x_right(s: float, y: ndarray, x_max_km: float) float[source]
Stop when ray exits right boundary.
- PyRayHF.library.event_z_bottom(s: float, y: ndarray, z_min_km: float) float[source]
Stop when ray leaves the bottom of the domain.
- PyRayHF.library.event_z_top(s: float, y: ndarray, z_max_km: float) float[source]
Stop when ray leaves the top of the domain.
- PyRayHF.library.find_X(n_e, f)[source]
Calculate the square of the plasma freq over the square of the ion freq.
- Parameters:
- n_earray-like
Electron density in m^-3.
- farray-like
Ionosonde frequency in Hz.
- Returns:
- Xfloat or array-like
Ratio (f_N / f)^2.
- PyRayHF.library.find_Y(f, b)[source]
Calculate Y: the electron gyrofrequency to ionosonde frequency ratio.
- Parameters:
- farray-like
Ionosonde frequency in Hz.
- barray-like
Magnetic field magnitude in Tesla.
- Returns:
- Yarray-like
Electron gyrofrequency / ionosonde frequency.
- PyRayHF.library.find_mean_gradient_error(atlon, atlat, arlon, arlat, year, month, day, UT, F107)[source]
Estimate the mean horiz-gradient-induced foF2 error along T and R GCD.
- Parameters:
- atlonndarray
Transmitter longitudes [deg].
- atlatndarray
Transmitter latitudes [deg].
- arlonndarray
Receiver longitudes [deg].
- arlatndarray
Receiver latitudes [deg].
- yearint
Year of the PyIRI specification.
- monthint
Month of the PyIRI specification.
- dayint
Day of the PyIRI specification.
- UTfloat
Universal Time [hours].
- F107float
F10.7 solar flux index [sfu].
- Returns:
- a_mean_errorndarray
Mean percent foF2 deviation along each T-R path relative to the midpoint value [%]. Positive values indicate higher foF2 away from the midpoint.
- F2_middict
PyIRI F2-region output at the midpoint locations, including foF2 and associated parameters.
Notes
For each transmitter-receiver (T-R) pair, this function samples the ionosphere along the great-circle path between the two locations, computes the foF2 variation relative to the midpoint value, and returns the mean percent deviation. The midpoint foF2 is treated as the reference, consistent with the midpoint-assumption framework.
Sampling is performed uniformly along the great-circle distance between each transmitter and receiver. foF2 (rather than NmF2) is used to quantify horizontal gradients, avoiding logarithmic scaling effects. The result provides a compact scalar metric describing how strongly horizontal structure violates the midpoint assumption for each link.
- PyRayHF.library.find_mu_mup(X, Y, bpsi, mode, *, y_tol: float = 1e-12) tuple[ndarray, ndarray][source]
Calculate the phase and group refractive indices (μ and μ’).
- Parameters:
- Xarray-like
Ratio of plasma and transmission frequencies squared.
- Yarray-like
Ratio of electron gyrofrequency and transmission frequency.
- bpsiarray-like
Angle ψ between wave vector and magnetic field in degrees.
- modestr
‘O’ for ordinary or ‘X’ for extraordinary wave mode.
- y_tolflt
Tollerance to determine if plasma is magnetized or not.
- Returns:
- muarray-like
Phase refractive index μ.
- muparray-like
Group refractive index μ’.
Notes
When Y ≈ 0 (unmagnetized plasma), use isotropic formulas: mu = sqrt(1 - X) for X < 1, else NaN mup = 1 / mu Otherwise, fall through to the existing magnetized Appleton-Hartree logic.
- PyRayHF.library.find_turning_point(z: ndarray, mu: ndarray, p: float) float[source]
Locate altitude where μ crosses the Snell invariant p.
Uses linear interpolation between bracketing nodes.
- Parameters:
- znp.ndarray
1D array of altitudes [km], monotonically increasing.
- munp.ndarray
1D array of refractive index values corresponding to each altitude.
- pfloat
Snell invariant (μ sinθ), constant along the ray path.
- Returns:
- z_turnfloat
Altitude of turning point [km].
- PyRayHF.library.find_vh(X, Y, bpsi, dh, alt_min, mode)[source]
Calculate virtual height for given mode.
- Parameters:
- Xarray-like
Plasma to ionosonde frequency ratio squared.
- Yarray-like
Electron gyrofrequency to ionosonde frequency ratio.
- bpsiarray-like
Angle between wave vector and magnetic field (degrees).
- dharray-like
Vertical layer thickness in km.
- alt_minfloat
Minimum altitude in km.
- modestr
“O” or “X” mode.
- Returns:
- vharray-like
Virtual height in km.
- PyRayHF.library.freq2den(frequency)[source]
Convert plasma frequency to plasma density.
- Parameters:
- frequencyfloat or array-like
Plasma frequency in Hz.
- Returns:
- densityfloat or array-like
Plasma density in m^-3.
- PyRayHF.library.generate_input_1D(year, month, day, UT, tlat, tlon, aalt, F107, save_path='')[source]
Compute 1D PyIRI/IGRF input data for raytracing in PyRayHF.
- Parameters:
- yearint
Four digit year in C.E.
- monthint
Integer month
- dayint
Integer day of month
- UTint
Universal time (UT) in hours
- tlatfloat
Latitude of transmitter in degrees
- tlonfloat
Longitude of transmitter in degrees
- aaltarray-like
Array of altitude grid points in km (max 1000 km)
- F107float
User provided F10.7 solar flux index in SFU.
- save_pathstr
Full file path for saving output data (must include .p file extension) If left blank, the output will not be saved toa file. (default=’’)
- Returns:
- out_datadict
‘alt’ : z coordinate array of vertical grid in km ‘den’ : Array of electron density in m^-3 ‘bmag’ : Array of magnetic field strenth in T ‘bpsi’ : Array of magnetic field angle to vertical in degrees ‘F2’ : PyIRI output dictionary for F2 region at (tlon, xlat) ‘F1’ : PyIRI output dictionary for F1 region at (tlon, tlat) ‘E’ : PyIRI output dictionary for E region at (tlon, tlat) ‘Es’ : PyIRI output dictionary for Es region at (tlon, tlat) ‘year’ : Year used to run PyIRI for this data ‘month’ : Month used to run PyIRI for this data ‘day’ : Day of month used to run PyIRI for this data ‘UT’ : Unniversal time used to run PyIRI for this data ‘F107’ : F10.7 in SFU used to run PyIRI for this data ‘tlat’ : Latitude in degrees of transmitter ‘tlon’ : Longitude in degrees of transmitter
Notes
Given date/time, solar conditions, HF transmitter location, and desired grid parameters, this function uses PyIRI and IGRF to generate electron density and magnetic field data in a 1D (vertical) grid that can be used for vertical or 2D Snell’s-law ray tracing input to PyRayHF.
- PyRayHF.library.generate_input_2D(year, month, day, UT, tlat, tlon, dx, aalt, gcd, az, F107, save_path='')[source]
Compute 2D PyIRI/IGRF input data for raytracing in PyRayHF.
- Parameters:
- yearint
Four digit year in C.E.
- monthint
Integer month
- dayint
Integer day of month
- UTint
Universal time (UT) in hours
- tlatfloat
Latitude of transmitter in degrees
- tlonfloat
Longitude of transmitter in degrees
- dxfloat
Horizontal resolution of output grid in km
- aaltarray-like
Array of altitude grid points in km (max 1000 km)
- gcdfloat
Great circle distance in km from transmitter to end of domain (The horizontal span of the output domain)
- azfloat
Azimuth from transmitter in degrees that defines the orientation of the output domain (measured clockwise from geographic North).
- F107float
User provided F10.7 solar flux index in SFU.
- save_pathstr
Full file path for saving output data (must include .p file extension) If left blank, the output will not be saved toa file. (default=’’)
- Returns:
- out_datadict
‘xgrid’ : x coordinate array of horizontal grid in km ‘zgrid’ : z coordinate array of vertical grid in km ‘xlat’ : Latitude in degrees of each point in xgrid ‘xlon’ : Longitude in degrees of each point in xgrid ‘den’ : 2D array of electron density in m^-3 ‘bmag’ : 2D array of magnetic field strenth in T ‘bpsi’ : 2D array of magnetic field angle to vertical in degrees ‘F2’ : PyIRI output dictionary for F2 region at all (xlon, xlat) ‘F1’ : PyIRI output dictionary for F1 region at all (xlon, xlat) ‘E’ : PyIRI output dictionary for E region at all (xlon, xlat) ‘Es’ : PyIRI output dictionary for Es region at all (xlon, xlat) ‘year’ : Year used to run PyIRI for this data ‘month’ : Month used to run PyIRI for this data ‘day’ : Day of month used to run PyIRI for this data ‘UT’ : Unniversal time used to run PyIRI for this data ‘F107’ : F10.7 in SFU used to run PyIRI for this data ‘tlat’ : Latitude in degrees of transmitter ‘tlon’ : Longitude in degrees of transmitter ‘az’ : Azimuth from transmitter in degrees (measured clockwise from
geographic north) that defines the orientation of the output domain
Notes
Given date/time, solar conditions, HF transmitter location, ray azimuth, and desired grid parameters, this function uses PyIRI and IGRF to generate electron density and magnetic field data in a 2D (horizontal VS vertical) grid that can be used for oblique ray tracing input to PyRayHF.
- PyRayHF.library.great_circle_point(tlat, tlon, gcd, az)[source]
Get lat/lon of a GCD point from an origin point.
- Parameters:
- tlat, tlonfloat
Lattitude and longitude of origin [degrees]
- gcdarray-like
Great circle distance from origin to destination point [km]
- azfloat
Azimuth (clockwise from north) from origin to destination point [degrees]
- Returns:
- rlat, rlonarray-like
Lattitude and longitude of destination point [degrees]
Notes
Assumes spherical earth (not ellipsoid)
- PyRayHF.library.make_n_and_grad(n_interp: RegularGridInterpolator, dn_dx_interp: RegularGridInterpolator, dn_dz_interp: RegularGridInterpolator) Callable[[ndarray, ndarray], Tuple[ndarray, ndarray, ndarray]][source]
Return a function (x, z) -> (n, dndx, dndz).
- PyRayHF.library.minimize_parameters(F2, F1, E, f_in0, vh_obs0, alt, b_mag, b_psi, method='brute', percent_sigma=20.0, step=1.0, mode='O', n_points=200, bottom_type='B_bot')[source]
Minimize F2 layer parameters (hmF2 and B_bot) to fit observed VH.
- Parameters:
- F2dict
Initial F2 layer parameters. Must include ‘Nm’, ‘hm’, and ‘B_bot’.
- F1dict
Initial F1 layer parameters.
- Edict
Initial E layer parameters.
- f_in0ndarray
Input frequencies [MHz].
- vh_obs0ndarray
Observed virtual heights [km].
- altndarray
Altitude array [km].
- b_magndarray
Magnetic field magnitude array [nT].
- b_psindarray
Magnetic field dip angle array [degrees].
- methodstr
Method of minimization in lmfit: “brute”: (default) A grid search method for finding a global minimum. “levenberg-marquardt”: Generally fast and effective for many curve-fitting needs. “powell”: Another derivative-free method.
- percent_sigmaflt
How far off from the background value to deviate. Default is 20%. If the speed needs to be increase, decrease this parameter.
- stepflt
Step size in km for brute minimization. If the speed needs to be increase, increase this parameter.
- modestr
‘O’ or ‘X’ mode. The default is ‘O’.
- n_pointsint
Number of desired vertical grid points. Default is 200.
- bottom_typestr
Type of the F2 bottom formalizm. Default is ‘B_bot’, which construncts bottom side of F2 using a single thickness parameter. Other option is ‘B0_B1’ which uses an IRI formalizm.
- Returns:
- vh_resultndarray
Virtual height after parameter fitting [km].
- EDP_resultndarray
Reconstructed electron density profile after fitting [m^-3].
- F2_fitdict
F2 dictionary with updated parameters.
- PyRayHF.library.model_VH(F2, F1, E, f_in, alt, b_mag, b_psi, mode='O', n_points=200, bottom_type='B_bot')[source]
Compute vertical virtual height using a modeled EDP and raytrace.
- Parameters:
- F2dict
Dictionary of F2 layer parameters. Must include: - ‘Nm’: peak electron density (NmF2) - ‘hm’: peak height (hmF2) - ‘B_bot’: thickness of the bottomside of the F2 layer
- F1dict
Dictionary of F1 layer parameters. Must include: - ‘P’: shape factor or profile parameter
- Edict
Dictionary of E layer parameters. Must include: - ‘hm’: peak height of the E layer
- f_inndarray
Input frequency [MHz].
- altndarray
1D array of altitudes [km].
- b_magndarray
1D array of magnetic field magnitudes [nT].
- b_psindarray
1D array of magnetic field dip angles [rad].
- modestr
‘O’ or ‘X’ mode. Default is ‘O’ mode.
- n_pointsint
Number of vertical grid points. Default is 200.
- bottom_typestr
Type of the F2 bottom formalizm. Default is ‘B_bot’, which construncts bottom side of F2 using a single thickness parameter. Other option is ‘B0_B1’ which uses an IRI formalizm.
- Returns:
- vh_Ondarray
Virtual height trace (O-mode) [km].
- EDPndarray
Reconstructed electron density profile [m^-3].
- PyRayHF.library.n_and_grad(x: ndarray, z: ndarray, n_interp: RegularGridInterpolator, dn_dx_interp: RegularGridInterpolator, dn_dz_interp: RegularGridInterpolator) Tuple[ndarray, ndarray, ndarray][source]
Evaluate n, ∂n/∂x, and ∂n/∂z at points (x, z).
- Parameters:
- xarray_like
Horizontal positions [km]; scalar or array.
- zarray_like
Altitudes [km]; scalar or array.
- Returns:
- nnp.ndarray
Refractive index at (x, z). Shape equals the broadcasted shape of inputs.
- dndxnp.ndarray
Partial derivative ∂n/∂x [1/km] at (x, z). Same shape as n.
- dndznp.ndarray
Partial derivative ∂n/∂z [1/km] at (x, z). Same shape as n.
Notes
Inputs are broadcast to a common shape, flattened for one batched interpolation, then reshaped back—this minimizes overhead during ODE stepping. Outside the grid hull, values are fill_value_n and fill_value_grad (unless bounds_error=True).
- PyRayHF.library.n_and_grad_rphi(phi: ndarray, r: ndarray, n_interp: RegularGridInterpolator, dn_dr_interp: RegularGridInterpolator, dn_dphi_interp: RegularGridInterpolator) Tuple[ndarray, ndarray, ndarray][source]
Evaluate μ(r, φ) and its gradients at given coordinates.
- Parameters:
- phiarray_like
Azimuthal coordinate [rad]. Scalar or array. Will broadcast with r.
- rarray_like
Radial coordinate [km] (Earth radius + altitude). Scalar or array.
- n_interpRegularGridInterpolator
Interpolator for μ(r, φ).
- dn_dr_interpRegularGridInterpolator
Interpolator for ∂μ/∂r.
- dn_dphi_interpRegularGridInterpolator
Interpolator for ∂μ/∂φ.
- Returns:
- nnp.ndarray
Refractive index μ at (r, φ). Shape matches broadcasted inputs.
- dn_drnp.ndarray
Partial derivative ∂μ/∂r at (r, φ).
- dn_dphinp.ndarray
Partial derivative ∂μ/∂φ at (r, φ).
- PyRayHF.library.oblique_to_vertical(range_km, group_path_km, freq_oblique_mhz, R_E=6371.0)[source]
Convert oblique ionogram to vertical equivalent using spherical Earth.
- Parameters:
- range_kmfloat
Ground distance between transmitter and receiver [km]
- group_path_kmarray-like
Oblique group path (total propagation distance) [km]
- freq_oblique_mhzarray-like
Oblique frequency [MHz]
- R_Eflt
Earth’s radius in [km]. Default is 6371 km.
- Returns:
- freq_vertical_mhzarray-like
Equivalent vertical frequency [MHz]
- height_virtual_kmarray-like
Virtual height at midpoint [km]
- PyRayHF.library.ray_rhs_cartesian(s: float, y: ndarray, n_and_grad: Callable[[ndarray, ndarray], Tuple[ndarray, ndarray, ndarray]], renormalize_every: int, eval_counter: Dict[str, int]) ndarray[source]
Right-hand side of the 2D ray equations in Cartesian coordinates.
- Parameters:
- sfloat
Arc length [km].
- yndarray
State vector [x, z, vx, vz].
- n_and_gradcallable
Function returning (n, dndx, dndz) at (x, z).
- renormalize_everyint
Frequency (in calls) to re-normalize direction vector.
- eval_counterdict
Mutable counter used for tracking RHS evaluations.
- Returns:
- dydsndarray
Derivatives [dx/ds, dz/ds, dvx/ds, dvz/ds].
- PyRayHF.library.regrid_to_nonuniform_grid(f, n_e, b, bpsi, aalt, mode='O', n_points=200, dh=1e-06)[source]
Regrid profile to smooth non-uniform vertical grid.
- Parameters:
- farray-like
Ionosonde frequency in Hz.
- n_earray-like
Electron density in m^-3.
- barray-like
Magnetic field magnitude.
- bpsiarray-like
Angle to magnetic field vector in degrees.
- aaltarray-like
Altitude profile in km.
- modestr
‘O’ or ‘X’ propagation mode. Default ‘O’.
- n_pointsint
Points in new vertical grid.
- dhflt
How close to the reflection height do we want to get. Default is 1e-6 km.
- Returns:
- regriddeddict
Dictionary with re-gridded arrays
- PyRayHF.library.residual_VH(params, F2_init, F1_init, E_init, f_in, vh_obs, alt, b_mag, b_psi, mode='O', n_points=200, bottom_type='B_bot')[source]
Compute the residuals between observed and modeled VHs.
- Parameters:
- paramslmfit.Parameters
Parameters to be optimized, containing: - ‘NmF2’: peak electron density of F2 layer - ‘hmF2’: peak height of F2 layer - ‘B_bot’: thickness of F2 bottomside
- F2_initdict
Initial F2 layer parameters.
- F1_initdict
Initial F1 layer parameters.
- E_initdict
Initial E layer parameters.
- f_infloat
Input frequency [MHz].
- vh_obsndarray
Observed virtual heights [km].
- altndarray
Altitude array [km].
- b_magndarray
Magnetic field magnitude array [nT].
- b_psindarray
Magnetic field dip angle array [rad].
- modestr
‘O’ or ‘X’ mode. Default is ‘O’ mode.
- n_pointsint
Number of vertical grid points. Default is 200.
- bottom_typestr
Type of the F2 bottom formalizm. Default is ‘B_bot’, which construncts bottom side of F2 using a single thickness parameter. Other option is ‘B0_B1’ which uses an IRI formalizm.
- Returns:
- residualndarray
Flattened array of residuals between observed and modeled virtual heights [km].
- PyRayHF.library.rhs_spherical(s: float, y: ndarray, n_and_grad_rphi: Callable[[ndarray, ndarray], Tuple[ndarray, ndarray, ndarray]], renormalize_every: int, eval_counter: Dict[str, int]) ndarray[source]
Calculate the right-hand side of the spherical ray equations.
- Parameters:
- sfloat
Current arc length along the ray [km].
- yndarray, shape (4,)
State vector [r, φ, v_r, v_φ]: - r : radial coordinate [km] - φ : azimuthal angle [rad] - v_r : radial direction cosine - v_φ : tangential direction cosine
- n_and_grad_rphicallable
Function (φ, r) → (μ, ∂μ/∂r, ∂μ/∂φ), typically constructed using build_refractive_index_interpolator_rphi.
- renormalize_everyint
Frequency (in RHS evaluations) to re-normalize the tangent vector to ensure |v| = 1. Use 0 or None to disable.
- eval_counterdict
Dictionary used to track number of RHS evaluations: e.g., {‘n’: 0} will be incremented in-place.
- Returns:
- dydsndarray
Derivatives with respect to arc length s: [dr/ds, dφ/ds, dv_r/ds, dv_φ/ds].
Notes
Implements 2D spherical geometry (flat-Earth limit not assumed).
The equations conserve |v| ≈ 1 under small step sizes.
NaN or non-positive μ values return zero derivatives (halts ray).
Computes derivatives for the ODE system governing 2D spherical ray propagation (r, φ) in a refractive index field μ(r, φ). The equations describe the evolution of position and tangent components along the raypath with respect to arc length s.
The system is defined as:
\[ \begin{align}\begin{aligned}\begin{split}\\frac{dr}{ds} = v_r \\qquad \\frac{dφ}{ds} = \\frac{v_φ}{r}\end{split}\\\begin{split}\\frac{dv_r}{ds} = \\frac{1}{μ} \\left[ \\frac{∂μ}{∂r} - (∇μ · v)v_r \\right] + \\frac{v_φ^2}{r}\end{split}\\\begin{split}\\frac{dv_φ}{ds} = \\frac{1}{μ} \\left[ \\frac{1}{r} \\frac{∂μ}{∂φ} - (∇μ · v)v_φ \\right] - \\frac{v_r v_φ}{r}\end{split}\end{aligned}\end{align} \]where the gradient projection is given by: .. math:
∇μ · v = \\frac{∂μ}{∂r} v_r + \\frac{1}{r} \\frac{∂μ}{∂φ} v_φReferences
Haselgrove, J., “The Hamiltonian Ray Path Equations”, Proc. IEE (1955)
Budden, K. G., The Propagation of Radio Waves, Cambridge Univ. Press,
1985
- PyRayHF.library.save_to_file(output, file_path)[source]
Save dictionary to a pickle file.
- Parameters:
- outputdict
Dictionary to save to pickle file
- file_pathstring
Full filepath (including .p extension) of output file
- PyRayHF.library.smooth_nonuniform_grid(start, end, n_points, sharpness)[source]
Generate smooth non-uniform grid from start to end.
- Parameters:
- startfloat
- endfloat
- n_pointsint
- sharpnessfloat
Controls how sharply resolution increases near end.
- Returns:
- xndarray
Non-uniformly spaced grid.
- PyRayHF.library.tan_from_mu_scalar(mu_val: float, p: float) float[source]
Compute tanθ safely for Snell’s law in plasma.
- Parameters:
- mu_valfloat
Phase refractive index μ at altitude.
- pfloat
Snell invariant (μ0 sinθ0).
- Returns:
- tanθfloat
Tangent of propagation angle relative to vertical.
Notes
This function finds tah_theta from μ * sin(θ) = p. tan(θ) = sin(θ) / cos(θ), and cos(θ) = sqrt(1−sin^2(θ)) tan(θ) = (p/μ) / sqrt(1−(p/μ)^2) = p / sqrt(μ^2 − p^2)
- PyRayHF.library.trace_ray_cartesian_gradient(n_and_grad: Callable[[ndarray, ndarray], Tuple[ndarray, ndarray, ndarray]], mup_func: Callable[[ndarray, ndarray], ndarray], x0_km: float, z0_km: float, elevation_deg: float, s_max_km: float = 5000.0, *, rtol: float = 1e-07, atol: float = 1e-09, max_step_km: float | None = None, z_ground_km: float = 0.0, z_min_km: float = -1.0, z_max_km: float = 1000.0, x_min_km: float = -1000000.0, x_max_km: float = 1000000.0, renormalize_every: int = 50) Dict[str, Any][source]
Trace a 2D ray in a horizontally varying refractive index field μ(x, z).
- Geometry is integrated via:
dr/ds = v, ||v|| = 1 dv/ds = (1/μ) [∇μ - (∇μ·v) v]
- Group delay is integrated using μ’(x, z):
τ = ∫ (μ’/c) ds
- Parameters:
- n_and_gradcallable
(x, z) → (μ, ∂μ/∂x, ∂μ/∂z). Usually built with build_refractive_index_interpolator(…).
- mup_funccallable
(x, z) → μ’(x, z). Must be built with build_mup_function(…).
- x0_km, z0_kmfloat
Launch point [km].
- elevation_degfloat
Launch elevation above horizontal [deg].
- s_max_kmfloat
Max path length [km].
- rtol, atolfloat
ODE solver tolerances.
- max_step_kmfloat or None
Max solver step size [km].
- z_ground_km, z_min_km, z_max_kmfloat
Vertical domain limits [km].
- x_min_km, x_max_kmfloat
Horizontal domain limits [km].
- renormalize_everyint
Re-normalize v every N evaluations.
- Returns:
- resultdict
Notes
This model assumes a 2D Cartesian (flat-Earth) geometry.
μ controls bending; μ’ controls group delay.
NaNs or invalid μ terminate integration.
Return dictionary keys: ‘sol’ : OdeResult, # full solve_ivp solution object ‘t’ : ndarray, # integration parameter (path length) [km] ‘x’ : ndarray, # horizontal coordinate [km] ‘z’ : ndarray, # altitude [km] ‘vx’ : ndarray, # horizontal unit-velocity component ‘vz’ : ndarray, # vertical unit-velocity component ‘status’ : str, # ‘ground’, ‘domain’, ‘length’, etc. ‘group_path_km’ : float, # geometric path length [km] ‘group_delay_sec’ : float, # group delay τ = ∫ μ’/c ds [s] ‘x_midpoint’ : float, # midpoint x-coordinate [km] ‘z_midpoint’ : float, # midpoint altitude [km] ‘ground_range_km’ : float, # landing x-coordinate or NaN [km] ‘x_apex_km’ : float, # apex horizontal coordinate [km] ‘z_apex_km’ : float # apex altitude [km]
- PyRayHF.library.trace_ray_cartesian_snells(f0_Hz: float, elevation_deg: float, alt_km: ndarray, Ne: ndarray, Babs: ndarray, bpsi: ndarray, mode: str) Dict[str, float][source]
Stratified Snell’s law ray tracing (flat Earth, 2D Cartesian).
- Parameters:
- f0_Hzfloat
Frequency [Hz].
- elevation_degfloat
Launch elevation above horizontal [deg].
- alt_kmndarray
Altitude grid [km].
- Nendarray
Electron density [el/m^3].
- Babsndarray
Magnetic field strength [T].
- bpsindarray
Angle between B and k-vector [degrees].
- modestr
Wave mode: “O” or “X”.
- Returns:
- resultdict
Notes
This function models how a high-frequency radio wave propagates through the ionosphere, using Snell’s law adapted for a plasma medium. It calculates the trajectory of the ray as it leaves the ground, bends through the ionized atmosphere, reaches a turning point, and (if conditions allow) returns back toward Earth.
Background: Snell’s Law in a Plasma. In a uniform dielectric, Snell’s law states that nsinθ=constant, where n is the refractive index and θ is the propagation angle relative to the vertical. In a plasma, the refractive index isn’t constant but depends on: electron density (affects plasma frequency), magnetic field (splits O and X modes), wave frequency, and angle between wave vector and magnetic field. This gives two possible wave modes: the ordinary (O) and extraordinary (X) mode, each with a different effective refractive index. The function uses auxiliary functions find_X, find_Y, and find_mu_mup to compute these refractive indices as functions of altitude. Thus, the plasma-modified Snell’s law is applied: μ’sinθ=constant, where μ’ is the transverse refractive index for the chosen wave mode.
Specifics: Geometry (bending) uses phase index μ. Group delay integrates group index μ’ (mup). Down-leg is a perfect mirror of the up-leg about the apex.
Return dictionary has the following keys:
‘x’ : ndarray # surface distance along the ray [km] ‘z’ : ndarray # altitude along the ray [km] ‘group_path_km’ : float # total geometric path length [km] ‘group_delay_sec’: float # group delay [s] ‘x_midpoint’ : float # midpoint horizontal coordinate [km] ‘z_midpoint’ : float # midpoint altitude [km] ‘ground_range_km’: float # surface distance to landing point [km] ‘x_apex_km’ : float # apex horizontal coordinate [km] ‘z_apex_km’ : float # apex altitude [km]
- PyRayHF.library.trace_ray_spherical_gradient(n_and_grad_rphi: Callable[[ndarray, ndarray], Tuple[ndarray, ndarray, ndarray]], mup_func: Callable[[ndarray, ndarray], ndarray], x0_km: float, z0_km: float, elevation_deg: float, s_max_km: float = 6000.0, *, R_E: float | None = None, z_ground_km: float = 0.0, r_max_km: float | None = None, phi_min: float = -3.141592653589793, phi_max: float = 3.141592653589793, rtol: float = 1e-07, atol: float = 1e-09, max_step_km: float | None = 2.0, renormalize_every: int = 50) Dict[str, Any][source]
Raytrace in 2-D spherical using μ for geometry and μ’ for delay.
- Parameters:
- n_and_grad_rphicallable
(φ, r) → (μ, ∂μ/∂r, ∂μ/∂φ).
- mup_funccallable (REQUIRED)
(x, z) → μ’(x, z). Build with build_mup_function(…, geometry=”spherical”).
- x0_km, z0_kmfloat
Launch point [km]; x0 is surface arc distance, z0 altitude.
- elevation_degfloat
Launch elevation above local horizontal [deg].
- s_max_kmfloat
Max arclength to integrate [km].
- R_Efloat, optional
Earth radius [km]. Defaults to constants()[2] if None.
- z_ground_kmfloat
Ground altitude [km]; stop when r ≤ R_E + z_ground_km.
- r_max_kmfloat, optional
Max r; default R_E + 1200 km if None.
- phi_min, phi_maxfloat
Azimuth bounds [rad].
- rtol, atolfloat
ODE tolerances.
- max_step_kmfloat or None
Max solver step [km].
- renormalize_everyint
Re-normalize v every N RHS calls.
- Returns:
- dict
Notes
Return dictionary has the following keys: ‘t’ : ndarray, # integration parameter (path length) [km] ‘r’ : ndarray, # radial coordinate [km] ‘phi’ : ndarray, # angular coordinate [rad] ‘v_r’ : ndarray, # radial component of unit tangent vector ‘v_phi’ : ndarray, # angular component of unit tangent vector ‘x’ : ndarray, # surface distance [km] ‘z’ : ndarray, # altitude above Earth’s surface [km] ‘status’ : str, # termination condition (ground, domain, ..) ‘group_path_km’ : float, # geometric path length [km] ‘group_delay_sec’ : float, # group delay [s] ‘x_midpoint’ : float, # midpoint horizontal coordinate [km] ‘z_midpoint’ : float, # midpoint altitude [km] ‘ground_range_km’ : float, # landing surface distance [km] ‘x_apex_km’ : float, # apex horizontal coordinate [km] ‘z_apex_km’ : float # apex altitude [km]
Geometry: Integrates in spherical coordinates (r, φ) with tangent v = (v_r, v_φ):
dr/ds = v_r dφ/ds = v_φ / r dv_r/ds = (1/μ)[∂μ/∂r - (∇μ·v)v_r] + (v_φ²)/r dv_φ/ds = (1/μ)[(∂μ/∂φ)/r - (∇μ·v)v_φ] - (v_r v_φ)/r
where ∇μ·v = (∂μ/∂r)v_r + (∂μ/∂φ)(v_φ / r).
Delay Group delay integrates μ’ along the path:
τ = ∫ ( μ’(x, z) / c ) ds
with x = R_E φ (surface arc) and z = r − R_E.
- PyRayHF.library.trace_ray_spherical_snells(f0_Hz: float, elevation_deg: float, alt_km: ndarray, Ne: ndarray, Babs: ndarray, bpsi: ndarray, mode: str = 'O', *, dz_target_km: float = 1.0, apex_boost: float = 200.0, max_substeps: int = 400, R_E: float | None = None) Dict[str, float][source]
Stratified Snell’s law ray tracing (spherical Earth, 2D geometry).
- Parameters:
- f0_Hzfloat
Radio frequency [Hz].
- elevation_degfloat
Launch elevation above local horizontal [degrees].
- alt_kmndarray
Altitude grid [km].
- Nendarray
Electron density profile [el/m³].
- Babsndarray
Magnetic field strength [T].
- bpsindarray
Magnetic field inclination [degrees].
- modestr, default ‘O’
Wave mode: ‘O’ (ordinary) or ‘X’ (extraordinary).
- dz_target_kmfloat, default 1.0
Target altitude increment for apex refinement [km].
- apex_boostfloat, default 200.0
Sharpness multiplier that increases substeps near turning points.
- max_substepsint, default 400
Hard limit on number of adaptive substeps per altitude interval.
- R_Efloat or None, optional
Earth radius [km]. If None, defaults to value from constants().
- Returns:
- resultdict
Notes
- Physical formulation:
- In spherical geometry, Snell’s invariant becomes:
μ * r * sin(θ) = constant
where μ is the phase refractive index, r = R_E + z, and θ is the angle between the ray and the local vertical.
The ray is launched from ground level, bent according to μ(r), reflected at the turning point where μ * r = p, and mirrored down.
- Group delay:
The propagation delay is integrated along the ray using the group refractive index μ’ (mup):
τ = ∫ (μ’ / c) ds
where c is the speed of light in vacuum.
- Apex refinement:
- Near the turning point, the derivative
dφ/dz = p / [ r * sqrt((μ r)² - p²) ]
becomes sharply peaked, making coarse integration unstable. To resolve this, the algorithm adaptively subdivides altitude steps where |μ r - p| is small, increasing resolution toward the apex while capping the total substeps with max_substeps.
- Comparison to Cartesian model:
This function extends the flat-Earth Snell’s law formulation (trace_ray_cartesian_snells) to spherical geometry. For large R_E, both solutions converge within numerical precision.
Return dictionary has the following keys: ‘x’ : ndarray, # horizontal coordinate [km] ‘z’ : ndarray, # altitude along the ray [km] ‘group_path_km’ : float, # total geometric path length [km] ‘group_delay_sec’ : float, # group delay [s] ‘x_midpoint’ : float, # midpoint horizontal coordinate [km] ‘z_midpoint’ : float, # midpoint altitude [km] ‘ground_range_km’ : float, # landing surface distance [km] ‘x_apex_km’ : float, # apex horizontal coordinate [km] ‘z_apex_km’ : float # apex altitude [km]
- PyRayHF.library.vertical_forward_operator(freq, den, bmag, bpsi, alt, mode='O', n_points=200)[source]
Calculate virtual height from ionosonde freq and ion profile.
- Parameters:
- freqarray-like
Frequency in MHz.
- denarray-like
Electron density in m^-3.
- bmagarray-like
Magnetic field magnitude in Tesla.
- bpsiarray-like
Angle to magnetic field vector.
- altarray-like
Altitude profile in km.
- modestr
‘O’ or ‘X’ propagation mode. Default ‘O’.
- n_pointsint
Number of vertical grid points. Default is 200.
- Returns:
- vhndarray
Virtual height in km.
- PyRayHF.library.vertical_to_magnetic_angle(inclination_deg)[source]
Calculate angle between vertical and magnetic field vector.
- Parameters:
- inclination_degfloat or ndarray
Magnetic inclination in degrees (positive = downward).
- Returns:
- vertical_anglefloat or ndarray
Angle between vertical and magnetic field in degrees.