Source code for ibpmodel.ibpforward

#!/usr/bin/env python3
"""This module contains the application functions for the calculation of the IBP index as well as the graphical visualization.
"""
from .ibpcalc import *
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker

[docs] def calculateIBPindex(day_month=0, longitude=list(range(-180,180,5)), local_time=np.arange(-6,6.1,0.1), f107=150, coeff=None, elecDensity=False): '''Calculates the Ionospheric Bubble propability index based on the input parameters. Returns a *pandas.DataFrame* with input parameters and IBP index. Parameters ---------- day_month : int or str or list, optional Day of year (*int*) or the month of the year (*str*). *int*: Day of the year, ``0 <= doy <= 365``. The value 0 means it should be calculated based on every month. *str*: Abbreviated month name. ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] The default is 0. longitude : int or list of ints, optional The geographical longitude(s), ``-180 <= longitude <= 180``. The default is `list(range(-180,180,5))`. local_time : int or float or list, optional The local time, ``-6.0 <= local_time <= 24``. The default is `np.arange(-6,6.1,0.1)`. f107 : int or float or list, optional The Solar Radio Flux (F10.7 index), ``60.0 <= f107`` if elecDensity is True otherwise ``80.0 <= f107``. The default is 150. coeff : None or str, optional Name of the coefficient file. The default is None. elecDensity : bool, optional Use of the electron density. The default is False. Returns ------- df : pandas.DataFrame contains the columns: Doy (Day(s) of the year), Month (Month(s) from the day of the year), Lon (Longitude(s)), LT (Local Time(s)), F10.7 (solar index(es)), IBP (Ionospheric Bubble Index, value(s) between 0.0 and 1.0). ''' df = pd.DataFrame(columns=['Doy','Month','Lon','LT','F10.7','IBP']) if day_month == 0: day_of_year = np.array([ doyFromMonth(i) for i in range(1,13) ]) else: day_of_year = np.array(checkDoyMonth(day_month)) longitude_range = range(-180,181) longitude = checkParameter(longitude, longitude_range).astype(int) longitude[longitude == 180] = -180 local_time_range = range(-6,25) local_time = checkParameter(local_time, local_time_range) f107 = checkSolarRadioRange(f107, elecDensity) data = read_model_file(coeff, elecDensity) parts = tiler(day_of_year, longitude, local_time, f107) for i, c in enumerate(['Doy', 'Lon', 'LT', 'F10.7']): df[c] = parts[i] df['Month'] = [ monthFromDoy(i) for i in df['Doy'] ] df['IBP'] = compute_probability_exp( df['Doy'].to_numpy(), df['Month'].to_numpy(), df['Lon'].to_numpy(), df['LT'].to_numpy(), df['F10.7'].to_numpy(), data=data) df['IBP'] = df['IBP'].round(4) return df
[docs] def butterflyData(f107=150, coeff=None, elecDensity=False): '''Calculates the Ionospheric Bubble Propability Index for all months (using the center DOY of each month) and all integer longitudes (resolution of 5 degree) using Local_Time of range -5 to 1 and a fixed value of F10.7. IBP index is then averaged from the Local_Times. Parameters ---------- f107 : int, optional The Solar Radio Flux (F10.7 index). The default is 150. coeff : None or str, optional Name of the coefficient file. The default is None. elecDensity : bool, optional Use of the electron density. The default is False. Returns ------- out_data : numpy.array [[month],[longitude],[IBP index]]. ''' f107 = checkSolarRadioRange(f107, elecDensity) month_range = np.arange( 1, 13, 1) longitude_range = np.arange(-180, 179, 5.0) local_time_range = np.arange( -5, 1, 0.01) month, longitude, local_time, f107 = tiler( np.array(month_range,dtype='int'),longitude_range,local_time_range,f107) data = read_model_file(coeff, elecDensity) day_of_year = np.array([ doyFromMonth(t) for t in month ]) result = compute_probability_exp( day_of_year,month,longitude,local_time,f107,data) out_data = np.array(tile_aggregate(result,month_range,longitude_range,local_time_range)).transpose() return out_data
[docs] def getcolorbar(cmap, level=np.arange(0.0, 1.05, 0.05)): '''Applies level to colormap. Parameters ---------- cmap : matplotlib.colors.Colormap level : array-like Returns ------- matplotlib.cm.ScalarMappable ''' norm = mpl.colors.BoundaryNorm(level, cmap.N) return mpl.cm.ScalarMappable(norm=norm, cmap=cmap)
[docs] def setcolorbar(scalarmap, fig, ax, **kwargs): '''Sets colorbar to figure on the specified axis. Parameters ---------- scalarmap : matplotlib.cm.ScalarMappable fig : matplotlib.figure.Figure ax : matplotlib.axes Returns ------- colorbar ''' cbar = fig.colorbar(scalarmap, ax=ax, label='Ionospheric Bubble Probability', **kwargs) return cbar
[docs] def checkcmap(cmap): '''Check if variable is a color map. Parameters ---------- cmap : str or matplotlib.colors.Colormap Returns ------- matplotlib.colors.Colormap ''' try: if isinstance(cmap, str): cmap = mpl.colormaps[cmap] if not isinstance(cmap, (mpl.colors.LinearSegmentedColormap, mpl.colors.ListedColormap)): raise ValueError(f"'{cmap}' of type {type(cmap)} is not a valid for colormap") except Exception as err: print(err) print("Default colormap 'viridis' is used!") cmap = mpl.colormaps['viridis'] return cmap
[docs] def plotIBPindex(doy, f107=150, ax=None, coeff=None, elecDensity=False, cmap='coolwarm', colors='b', linewidths=0.2, **kwargs): '''Create a contour plot of IBP index for the given day. The resolution along the longitude is 5 degree. Local time spans from 6 pm to 6 am with a resolution of 0.1 hours. Default colormap is 'coolwarm'. Parameters ---------- doy : int or str Day of year (*int*) or the month of the year (*str*). *int*: Day of the year, ``0 <= doy <= 365``. The value 0 means it should be calculated based on every month. *str*: Abbreviated month name. ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] f107 : int or float, optional The Solar Radio Flux (F10.7 index). The default is 150. ax : matplotlib.axes, optional The Axes object in which the plot will be drawn. The default is None. coeff : str, optional Path of coefficient file. The default is None. elecDensity : bool, optional Use of the electron density. The default is False. cmap : str or Colormap, optional The colormap instance or registered colormap name to use. The default is 'coolwarm'. colors : color string or sequence of colors, optional The color of the contour lines. The default is 'blue'. linewidths : float, optional The line width of the contour lines. The default is 0.2. Returns ------- matplotlib.axes, matplotlib.cm.ScalarMappable ''' if isinstance(doy, (int, str)): doy = checkDoyMonth(doy)[0] else: raise ValueError(f"'{doy}' must be of type int or str, not {type(doy)}") df = calculateIBPindex(day_month=doy, f107=f107, coeff=coeff, elecDensity=elecDensity) value_size = np.unique(df['Lon'].to_numpy(), return_counts=True) value_size = ( len(value_size[0]), value_size[1][0] ) x = np.transpose(df['Lon'].to_numpy().reshape(value_size)) y = np.transpose(df['LT'].to_numpy().reshape(value_size)) z = np.transpose(df['IBP'].to_numpy().reshape(value_size)) if ax == None: fig, ax = plt.subplots(figsize = (9, 4)) pltshow = True else: pltshow = False cmap = checkcmap(cmap) levels = np.arange(0.0, 1.05, 0.05) scalarmap = getcolorbar(cmap, levels) ax.contourf(x, y, z, levels=levels, cmap=cmap, **kwargs) ax.contour(x, y, z, levels=levels, colors=colors, linewidths=linewidths, **kwargs) ticks_loc = ax.get_yticks().tolist() ax.yaxis.set_major_locator(mticker.FixedLocator(ticks_loc)) ax.set_yticklabels([f"{int(24+i)}:00" if i < 0 else f"0{int(i)}:00" for i in ticks_loc]) if elecDensity: title_string = f'IBP (electron density) at doy {doy} and F10.7 of {f107} sfu' else: title_string = f'IBP at doy {doy} and F10.7 of {f107} sfu' ax.set_title(title_string) ax.set_xlabel('Longitude in degree') ax.set_ylabel('Local Time') if pltshow: setcolorbar(scalarmap, fig, ax) plt.subplots_adjust(right=1, bottom=0.15) plt.show() else: return (ax, scalarmap)
[docs] def plotButterflyData(f107=150, ax=None, coeff=None, elecDensity=False, cmap='plasma_r', **kwargs): '''Create a contour plot of the result from function butterflyData(). Default colormap is 'plasma_r'. Parameters ---------- f107 : int or float, optional The Solar Radio Flux (F10.7 index). The default is 150. ax : matplotlib.axes, optional The Axes object in which the plot will be drawn. The default is None. coeff : str, optional Path of coefficient file. The default is None. elecDensity : bool, optional Use of the electron density. The default is False. cmap : str or Colormap, optional The colormap instance or registered colormap name to use. The default is 'plasma_r'. Returns ------- matplotlib.axes, matplotlib.cm.ScalarMappable ''' d = butterflyData(f107, coeff, elecDensity) y = np.transpose(np.reshape(d[:, 0], (12, 72))) x = np.transpose(np.reshape(d[:, 1], (12, 72))) z = np.transpose(np.reshape(d[:, 2], (12, 72))) if elecDensity: l = np.arange(0.0, 1.05, 0.05) else: l = np.arange(0.0, 0.85, 0.05) if ax == None: fig, ax = plt.subplots(figsize = (6.2, 5.0)) pltshow = True else: pltshow = False cmap = checkcmap(cmap) scalarmap = getcolorbar(cmap, l) ax.contourf(x, y, z, l, cmap = cmap, **kwargs) if elecDensity: title_string = f'Monthly IBP (electron density) with F10.7 of {f107} sfu' else: title_string = f'Monthly IBP with F10.7 of {f107} sfu' ax.set_title(title_string) ax.set_xlabel('Longitude in degree') ax.set_ylabel('Month') if pltshow: setcolorbar(scalarmap, fig, ax) plt.show() else: return ax, scalarmap