Case Study: NTSB Reports
This notebook provides an example of MIKA capabilties via a case study on NTSB reports. The capabilities shown in this example include: - Information Retrieval - Topic Modeling - FMEA extraction through custom NER - Trend Analysis
Case Study set up:
Package imports
Data import
[1]:
import sys, os
#sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)),"..","..")) #not working in notebook
sys.path.append(os.path.join("..",".."))
import numpy as np
import pandas as pd
from mika.utils import Data
from mika.ir import search
from datetime import datetime as dt
from mika.kd.topic_model_plus import Topic_Model_plus
from mika.kd.trend_analysis import plot_frequency_time_series, plot_metric_time_series, plot_metric_averages, make_pie_chart, chi_squared_tests, plot_risk_matrix, get_likelihood_FAA, identify_docs_per_fmea_row, calc_severity_per_hazard, add_hazards_to_docs, chi_squared_tests
from mika.kd import FMEA
from sklearn.feature_extraction.text import CountVectorizer
from sentence_transformers import SentenceTransformer
from torch import cuda
import matplotlib as mpl
import matplotlib.pyplot as plt
[2]:
os.chdir('../')
os.chdir('../')
[3]:
ntsb_filepath = os.path.join("data/NTSB/ntsb_full.csv")
ntsb_text_columns = ['narr_cause', 'narr_accf'] # narrative accident cause and narrative accident final
ntsb_document_id_col = 'ev_id'
ntsb_database_name = 'NTSB'
ntsb_data = Data()
ntsb_data.load(ntsb_filepath, preprocessed=False, id_col=ntsb_document_id_col, text_columns=ntsb_text_columns.copy(), name=ntsb_database_name, load_kwargs={'dtype':str})
ntsb_data.prepare_data(create_ids=False, combine_columns=ntsb_text_columns.copy(), remove_incomplete_rows=False)
Combining Columns…: 100%|██████████| 196535/196535 [00:04<00:00, 41292.74it/s]
data preparation: 0.08 minutes
[4]:
years_of_interest = ['2011', '2012', '2013', '2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021']
ntsb_data.data_df = ntsb_data.data_df.loc[ntsb_data.data_df['ev_year'].isin(years_of_interest)].drop_duplicates(subset='ev_id', keep="last").reset_index(drop=True) # keep the last record, this one has the phase of flight and mishap right before the accident
ntsb_data._Data__update_ids()
ntsb_data.data_df
[4]:
ev_id | damage | ev_highest_injury | inj_tot_f | ev_date | ev_year | ev_state | wind_dir_ind | wind_vel_ind | light_cond | ... | narr_accf | narr_cause | acft_make | acft_model | flt_plan_filed | flight_plan_activated | total_seats | Phase | Mishap Category | Combined Text | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 20110103X01024 | SUBS | FATL | 1.0 | 2011-01-01 00:00:00 | 2011 | MA | U | F | NITE | ... | The pilot and passenger were on a pleasure fli... | The pilot did not maintain separation from tre... | CESSNA | 310F | NONE | 4.0 | Approach-VFR Pattern Final | Control flight into terr/obj | The pilot did not maintain separation from tre... | |
1 | 20110103X35259 | SUBS | FATL | 1.0 | 2011-01-04 00:00:00 | 2011 | MO | U | F | NITE | ... | The accident occurred during the fourth leg of... | The pilot's loss of control for undetermined r... | CESSNA | 172H | NONE | 4.0 | Enroute-Cruise | Loss of control in flight | The pilot's loss of control for undetermined r... | |
2 | 20110103X42941 | SUBS | SERS | 0.0 | 2011-01-03 00:00:00 | 2011 | PA | U | F | NITE | ... | The instrument-rated pilot was on the return l... | The pilot's failure to maintain clearance from... | PIPER | PA-28-161 | NONE | N | 4.0 | Enroute-Cruise | Control flight into terr/obj | The pilot's failure to maintain clearance from... |
3 | 20110103X63632 | SUBS | NONE | 0.0 | 2011-01-02 00:00:00 | 2011 | NM | U | F | DAYL | ... | The pilot stated that during landing he lost d... | The pilot's failure to maintain directional co... | BELLANCA | 1419 | NONE | N | 4.0 | Landing-Landing Roll | Landing gear collapse | The pilot's failure to maintain directional co... |
4 | 20110104X52154 | SUBS | NONE | 0.0 | 2011-01-04 00:00:00 | 2011 | AZ | U | F | DAYL | ... | While parking the airplane, the student pilot ... | The student pilot's failure to maintain cleara... | PIPER | PA-28-181 | NONE | 4.0 | Taxi-from Runway | Collision with terr/obj (non-CFIT) | The student pilot's failure to maintain cleara... | |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
16909 | 20200908X33742 | SUBS | FATL | 3.0 | 2020-09-08 00:00:00 | 2020 | TN | U | F | DAYL | ... | Piper | PA28 | NONE | N | 4.0 | Uncontrolled Descent | Collision with terr/obj (non-CFIT) | |||
16910 | 20210929103995 | SUBS | MINR | 0.0 | 2021-09-28 00:00:00 | 2021 | FL | U | F | DAYL | ... | ROBINSON HELICOPTER COMPANY | R44 II | 4.0 | Standing-Engine(s) Operating | Loss of control on ground | |||||
16911 | 20190826X12752 | SUBS | NONE | 0.0 | 2019-08-26 00:00:00 | 2019 | CA | U | F | NDRK | ... | Lockheed | C130 | VFIF | Y | 7.0 | Initial Climb | Part(s) separation from AC | |||
16912 | 20200823X00819 | SUBS | NONE | 0.0 | 2020-08-22 00:00:00 | 2020 | NC | U | F | DAYL | ... | Aeronca | 11AC | NONE | 2.0 | Landing-Landing Roll | Collision with terr/obj (non-CFIT) | ||||
16913 | 20200921X53937 | DEST | FATL | 1.0 | 2020-09-21 00:00:00 | 2020 | FL | U | F | DAYL | ... | Vans | RV 8 | NONE | 2.0 | Enroute-Cruise | Fire/smoke (non-impact) |
16914 rows × 22 columns
Information Retrieval
Two model options are available for IR: 1. fine-tuned model 2. pre-trained distilroberta model
[5]:
# fine tuned model
model = SentenceTransformer("NASA-AIML/MIKA_Custom_IR")
#model = SentenceTransformer('all-distilroberta-v1') #uncomment to use pretrained model
ir_ntsb = search('narr_cause', ntsb_data, model)
embeddings_path = os.path.join('data', 'NTSB', 'ntsb_sentence_embeddings_finetune.npy')
ir_ntsb.get_sentence_embeddings(embeddings_path) # uncomment this if the embeddings do not yet exist
#ir_ntsb.load_sentence_embeddings(embeddings_path) # uncomment this if you wish to load sentence embeddings that already exist
queries = ['what components are vulnerable to fatigue crack', 'what are the consequences of a fuel leak', 'what are the risks of low visibility']
for query in queries:
print(query)
print(ir_ntsb.run_search(query, return_k=10, rank_k=10))
what components are vulnerable to fatigue crack
top_hit_idx top_hit_doc top_hit_scores \
0 37185 20121204X63622 0.746134
1 23081 20141027X62323 0.728395
2 39995 20141027X62323 0.728395
3 41744 20160114X73526 0.715234
4 24830 20160114X73526 0.715234
5 17989 20110809X03303 0.702911
6 34903 20110809X03303 0.702911
7 20253 20121130X01711 0.699882
8 37167 20121130X01711 0.699882
9 37185 20121204X63622 0.699882
top_hit_text
0 The total loss of engine power as a result of ...
1 The private pilot and a sport pilot-rated pass...
2 The loss of engine power during cruise flight ...
3 Failure of the left wing in flight due to comp...
4 The sport pilot was conducting a personal cros...
5 The pilot had just leveled off to cruise fligh...
6 A sudden loss of engine thrust due to the sepa...
7 The airplane was operating as a night, schedul...
8 The total loss of engine power as a result of ...
9 The total loss of engine power as a result of ...
what are the consequences of a fuel leak
top_hit_idx top_hit_doc top_hit_scores \
0 18698 20120129X84717 0.756848
1 35612 20120129X84717 0.756848
2 22747 20140812X10218 0.723396
3 39661 20140812X10218 0.723396
4 33896 20110128X23759 0.705061
5 16982 20110128X23759 0.705061
6 27222 20170710X71845 0.704668
7 44136 20170710X71845 0.704668
8 47247 20190716X10219 0.679851
9 30333 20190716X10219 0.679851
top_hit_text
0 The pilot stated that, during the preflight in...
1 The total loss of engine power due to fuel sta...
2 The pilot reported that the airplane's engine ...
3 The pilot’s failure to properly manage the air...
4 The pilot’s inadequate preflight inspection to...
5 The pilot requested that the airplane be “topp...
6 The pilot reported that, shortly after takeoff...
7 A total loss of engine power due to fuel starv...
8 The pilot's improper fuel planning, which resu...
9 The pilot reported that, after takeoff and whi...
what are the risks of low visibility
top_hit_idx top_hit_doc top_hit_scores \
0 16921 20110105X11652 0.562436
1 33835 20110105X11652 0.562436
2 16989 20110131X11636 0.526502
3 33903 20110131X11636 0.526502
4 42919 20160921X20513 0.518302
5 26005 20160921X20513 0.518302
6 22413 20140613X91656 0.513717
7 39327 20140613X91656 0.513717
8 22413 20140613X91656 0.484448
9 39327 20140613X91656 0.484448
top_hit_text
0 During the approximately 5 hour and 25 minute ...
1 The pilot's failure to maintain control of the...
2 The pilot reported that he was practicing nigh...
3 The pilot's failure to maintain control of the...
4 The pilot's decision to land in an area of low...
5 While maneuvering at low altitude for a water ...
6 The pilot arrived at the fixed-base operator o...
7 The pilot's failure to maintain a positive cli...
8 The pilot arrived at the fixed-base operator o...
9 The pilot's failure to maintain a positive cli...
Topic Modeling
Here we implement BERtopic via topic model plus to create a taxonomy of failure information.
[ ]:
tm = Topic_Model_plus(text_columns=ntsb_text_columns, data=ntsb_data, results_path=os.path.join(os.getcwd(),"examples/Case_Study_NTSB"))
vectorizer_model = CountVectorizer(ngram_range=(1, 3), stop_words="english") #removes stopwords
BERTkwargs={"top_n_words": 10, 'min_topic_size':25}
tm.bert_topic(count_vectorizor=vectorizer_model, BERTkwargs=BERTkwargs, from_probs=False)
tm.save_bert_model()
tm.save_bert_results(from_probs=False)
tm.save_bert_taxonomy() #saves taxonomy #takes 15 min to run
[7]:
taxonomy = pd.read_csv(os.path.join(tm.folder_path,'BERT_taxonomy.csv'), index_col=0) #print taxonomy
taxonomy = taxonomy.dropna(how='any').reset_index(drop=True)
taxonomy
[7]:
narr_cause | narr_accf | document IDs for row | number of documents for row | |
---|---|---|---|---|
0 | abort, abort takeoff, decision abort, decision... | airplane, pilot reported, pilot, reported, run... | ['20120515X10453', '20120531X13740', '20120907... | 10 |
1 | abort, abort takeoff, decision abort, decision... | airplane, pilot, runway, landing, engine, left... | ['20110609X25931', '20110706X70339', '20110805... | 41 |
2 | abort, abort takeoff, decision abort, decision... | carburetor, power, engine, carburetor heat, he... | ['20120430X00440', '20120514X11605'] | 2 |
3 | abort, abort takeoff, decision abort, decision... | fuel, tank, engine, fuel tank, power, tanks, p... | ['20111221X54903', '20200920X32151'] | 2 |
4 | abort, abort takeoff, decision abort, decision... | snow, airplane, snowcovered, pilot, reported, ... | ['20120316X94235'] | 1 |
... | ... | ... | ... | ... |
1149 | wing, left wing, right wing, spar, right, fail... | airplane, pilot reported, pilot, reported, run... | ['20120831X90624', '20130829X54643'] | 2 |
1150 | wing, left wing, right wing, spar, right, fail... | airplane, pilot, runway, landing, engine, left... | ['20110228X83526', '20110919X61206', '20120320... | 19 |
1151 | wing, left wing, right wing, spar, right, fail... | airplane, tailwheelequipped, reported, right, ... | ['20200519X04334'] | 1 |
1152 | wing, left wing, right wing, spar, right, fail... | flight, pilot, conditions, weather, accident, ... | ['20150505X85410', '20180404X13226'] | 2 |
1153 | wing, left wing, right wing, spar, right, fail... | taxiway, taxi, airplane, taxiing, wing, pilot,... | ['20210727103561'] | 1 |
1154 rows × 4 columns
FMEA using Named-Entity Recognition
[5]:
#definted according to FAA order 8040.4B: https://www.faa.gov/documentLibrary/media/Order/FAA_Order_8040.4B.pdf
def NTSB_severity(damage, inj_level, inj_tot_f, persons_onboard): #damage, ev_highest_injury, inj_tot_f
if float(persons_onboard) == 0:
persons_onboard = inj_tot_f
if inj_tot_f != 0 :
pct_fatal = inj_tot_f/persons_onboard
else:
pct_fatal = 0
#minimal: no injuries, no damage.
if inj_level == 'NONE' and damage == 'UKN':
severity = 'Minimal'
#minor: slight (MINR) damage, physical discomfort
elif inj_level == 'MINR' or inj_level == 'NONE':
#major: substaintail (SUBS) damage, injuries
if damage == 'SUBS':
severity = 'Major'
elif damage == 'DEST':
severity = 'Hazardous'
else:
severity = 'Minor'
#hazardous: multiple serious injuries, fatalities<2, hull loss (DEST)
elif inj_level == 'SERS' or (inj_level == 'FATL' and (inj_tot_f <= 2 or pct_fatal < 0.75)) or damage == 'DEST':
severity = 'Hazardous'
#catatrophic: fatalities > 2, or num person on board= num fatalities, hull loss (DEST)
elif inj_level == 'FATL' and (inj_tot_f > 2 or pct_fatal > 0.75):
severity = 'Catastrophic'
else:
severity = 'Minimal' #case with no reported fatalities, injury level, or damage level
return severity
def severity_func(df, numeric=True):
severity_dict = {'Catastrophic':5, 'Hazardous': 4, 'Major':3, 'Minor':2, 'Minimal':1}
severities = []
for i in range(len(df)):
severities.append(NTSB_severity(df.at[i, 'damage'], df.at[i, 'ev_highest_injury'], float(df.at[i, 'inj_tot_f'].replace('','0')), float(df.at[i, 'total_seats'].replace('','0'))))
if numeric == True:
df['severity'] = [severity_dict[severity] for severity in severities]
else:
df['severity'] = severities
return df
[7]:
#prepare the df for FMEA - drop repeat rows
fmea_input_df = ntsb_data.data_df.copy()
fmea_input_df = fmea_input_df.loc[~(fmea_input_df['Combined Text']=='')].reset_index(drop=True) # remove docs with no text
[8]:
model_checkpoint = "NASA-AIML/MIKA_BERT_FMEA_NER"
print(model_checkpoint)
device = 'cuda' if cuda.is_available() else 'cpu'
cuda.empty_cache()
print(device)
fmea = FMEA()
fmea.load_model(model_checkpoint)
print("loaded model")
input_data = fmea.load_data('Combined Text','ev_id', df=fmea_input_df, formatted=False)
print("loaded data")
preds = fmea.predict()
df = fmea.get_entities_per_doc()
fmea.group_docs_with_meta(grouping_col='Mishap Category', additional_cols=['Phase'])
fmea.grouped_df.to_csv(os.path.join(os.getcwd(),"examples/Case_Study_NTSB/ntsb_fmea_raw.csv"))
models\FMEA-ner-model\checkpoint-1424
cuda
loaded model
Token indices sequence length is longer than the specified maximum sequence length for this model (3132 > 512). Running this sequence through the model will result in indexing errors
loaded data
[9]:
fmea.calc_severity(severity_func, from_file=False)
fmea.calc_frequency(year_col="ev_year") #add year column
fmea.calc_risk()
fmea.post_process_fmea(phase_name='Phase', id_name='NTSB', max_words=10)
fmea.fmea_df.astype(str).to_csv(os.path.join(os.getcwd(),"examples/Case_Study_NTSB/NTSB_FMEA.csv"))
[28]:
mishaps_of_interest = ['Birdstrike','Midair collision', 'Loss of control in flight','Loss of control on ground','Turbulence encounter', 'Ground collision']
[37]:
fmea.fmea_df.loc[fmea.fmea_df.index.isin(mishaps_of_interest)].astype(str).to_csv(os.path.join(os.getcwd(),"examples/Case_Study_NTSB/NTSB_FMEA_truncated.csv"))
fmea.fmea_df.loc[fmea.fmea_df.index.isin(mishaps_of_interest)]
[37]:
Phase | Cause | Failure Mode | Effect | Control Process | Recommendations | Frequency | Severity | Risk | NTSB | |
---|---|---|---|---|---|---|---|---|---|---|
cluster | ||||||||||
Birdstrike | Approach-VFR Pattern Downwind; Enroute; Enrout... | at low, bird, surface, a, red - tailed, hawk, ... | in - flight, collision, with a, bird, large, p... | bird, substantial, damage, large, broke the fr... | was, towed to the gate, a, bird ingestion and ... | see the public, , enter, keep an, eye, on, land, | 4 | 3.0114942528735638 | 12.045977011494251 | 20170626X02552 |
Ground collision | Approach-VFR Pattern Downwind; Standing-Engine... | ', inadequate visual, lookout, failure, zodiac... | to see and avoid the, zodiac was, from the, pr... | hit, rear, vertical stabilize, were, destroyed... | radio, calls, position, reports, checked the t... | inform, , use caution, hold, pilot, clearance,... | 4 | 2.878504672897196 | 11.514018691588785 | 20140603X83103 |
Loss of control in flight | Approach-VFR Pattern Downwind; Approach-IFR Fi... | pilot's, fatigue, pilot, departed, night, test... | pilot's loss of, entered a, descending left, f... | und, airplane, spiraled, down, impacting an op... | intermediate, stops, radar track, toxicology, ... | , conform to its type, certificate, documentat... | 5 | 3.659551760939168 | 18.29775880469584 | 20190713X34059 |
Loss of control on ground | Approach-VFR Pattern Downwind; Approach-IFR Fi... | pre - existing crack in the weld, joint, const... | failure of the left main landing gear, st, lef... | the, structural, damage, to the, fuselage, rig... | right ailer, point, applied right rudder to, c... | , remain, reduce, land to the, north, take off... | 5 | 3.0433925049309667 | 15.216962524654834 | 20111104X64432 |
Midair collision | Enroute; Enroute-Descent; Landing; Maneuvering... | failure of both pilots to see and avoid the ot... | midair, collision, airplanes, collided, collid... | impacted the, terrain, a utility, pole, to, re... | wingtip -, - mounted strobe anticollision, lig... | alter, course, pass well, not have passed over... | 3 | 3.3968253968253967 | 10.19047619047619 | 20191205X95005 |
Turbulence encounter | Approach-VFR Pattern Downwind; Enroute; Enrout... | with, of, cumulonimbus, clouds, slowly, activi... | and, turbulence, tailwind, knots, tailwind sud... | indicated speed of the airplane quickly, incre... | captain activated the speed, brakes, disengage... | , expect light - to - moderate, before -, cabin | 4 | 3.792307692307692 | 15.169230769230769 | 20181001X33722 |
Trend Analysis
Now that we have rows of mishaps and failure information, we can look at trends in the mishap. In this case, we look at trends in: 1. mishap frequency over time 2. mishap severity over time 3. average mishap severity 3. distribution of mishaps over activated flight plans 4. distribution of mishaps over visibility conditions
[6]:
frequency, docs_per_row = identify_docs_per_fmea_row(ntsb_data.data_df, 'Mishap Category', 'ev_year', 'ev_id')
[7]:
mishaps_of_interest = ['Birdstrike','Midair collision', 'Loss of control in flight','Loss of control on ground','Turbulence encounter', 'Ground collision',]
years_of_interest = ['2011', '2012', '2013', '2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021']
frequency_set = {mishap:{year: frequency[mishap][year] for year in years_of_interest} for mishap in mishaps_of_interest}
doc_set = {mishap:{year: docs_per_row[mishap][year] for year in years_of_interest} for mishap in mishaps_of_interest}
[8]:
plot_frequency_time_series(frequency_set, metric_name='Frequency', line_styles=[],
markers=[], title="Frequency from 2011-2021", time_name="Year", xtick_freq=2,
scale=False, save=False, yscale='log', legend=True,
figsize=(6,4), fontsize=24)

[9]:
df_with_severities = severity_func(ntsb_data.data_df, numeric=True)
[10]:
severities, total_severities_hazard = calc_severity_per_hazard(doc_set, df_with_severities, 'ev_id', metric='max')
[11]:
plot_metric_time_series(metric_data=severities, metric_name="Severity", title="Average Severity from 2011-2021", time_name='Year', xtick_freq=2, show_std=False, save=False, figsize=(6,4), fontsize=24)

[12]:
plot_metric_averages(metric_data=severities, metric_name="Severity", show_std=True, title="Average Severity", save=False, legend=False, figsize=(8,4),fontsize=24)

[13]:
df_with_severities['sky_cond_nonceil'].unique()
sky_conditions_dict = {'CLER': 'clear',
'':'unknown',
'SCAT': 'scattered',
'FEW': 'few',
'UNK': 'unknown',
'OVCT': 'thin overcast',
'OVC': 'overcast',
'OBSC': 'obscured',
'BKNT': 'thin broken',
'BKN': 'broken',
'POBS': 'partially obscured',
'VV': 'indefinite',
'NONE': 'none'}
df_with_severities['sky_cond_nonceil_cleaned'] = [sky_conditions_dict[cond] for cond in df_with_severities['sky_cond_nonceil'].tolist()]
[14]:
df_with_severities['flight_plan_activated_cleaned'] = [val if val!='' else 'U' for val in df_with_severities['flight_plan_activated'].tolist()]
[15]:
make_pie_chart(doc_set, df_with_severities, 'flight_plan_activated_cleaned', mishaps_of_interest, 'ev_id', 'Activated Flight Plan', save=False, fontsize=12, pie_kwargs={'pctdistance':1.27}, figsize=(6,4), padding=10)

[16]:
make_pie_chart(doc_set, df_with_severities, 'sky_cond_nonceil_cleaned', mishaps_of_interest, 'ev_id', 'Sky Condition', save=False, fontsize=12, pie_kwargs={'pctdistance':1.27}, figsize=(6,4), padding=10)

[ ]:
df_with_hazards = add_hazards_to_docs(df_with_severities, id_field='ev_id', docs=doc_set)
stats_df, counts_dfs = chi_squared_tests(df_with_hazards, mishaps_of_interest, predictors=['flight_plan_activated_cleaned','sky_cond_nonceil_cleaned'], pred_dict={'flight_plan_activated_cleaned':'flight plan','sky_cond_nonceil_cleaned': 'sky condition'})
[18]:
stats_df
[18]:
Predictor | flight plan | sky condition | ||
---|---|---|---|---|
Measure | p-val | chi-squared | p-val | chi-squared |
Birdstrike | 0.000 | 44.813 | 0.027 | 10.929 |
Midair collision | 0.007 | 10.024 | 0.789 | 1.710 |
Loss of control in flight | 0.000 | 30.626 | 0.000 | 34.186 |
Loss of control on ground | 0.000 | 74.891 | 0.000 | 65.104 |
Turbulence encounter | 0.000 | 319.912 | 0.000 | 98.286 |
Ground collision | 0.005 | 10.670 | 0.040 | 10.004 |
[19]:
for df in counts_dfs:
display(counts_dfs[df])
N | U | Y | ||
---|---|---|---|---|
Hazard | Present | |||
Birdstrike | 0 | 18.343739 | 4.985338 | -23.329077 |
1 | -18.343739 | -4.985338 | 23.329077 | |
Midair collision | 0 | 14.496985 | -14.321509 | -0.175476 |
1 | -14.496985 | 14.321509 | 0.175476 | |
Loss of control in flight | 0 | 42.169032 | -86.260908 | 44.091877 |
1 | -42.169032 | 86.260908 | -44.091877 | |
Loss of control on ground | 0 | -118.701135 | 43.465236 | 75.235899 |
1 | 118.701135 | -43.465236 | -75.235899 | |
Turbulence encounter | 0 | 71.030330 | 8.283020 | -79.313350 |
1 | -71.030330 | -8.283020 | 79.313350 | |
Ground collision | 0 | 2.819085 | 14.042805 | -16.861890 |
1 | -2.819085 | -14.042805 | 16.861890 |
clear | unknown | few | scattered | thin overcast | ||
---|---|---|---|---|---|---|
Hazard | Present | |||||
Birdstrike | 0 | 12.706515 | -3.719641 | -7.401206 | -0.237436 | -1.348232 |
1 | -12.706515 | 3.719641 | 7.401206 | 0.237436 | 1.348232 | |
Midair collision | 0 | -3.161168 | -1.408892 | 2.871940 | 1.083954 | 0.614166 |
1 | 3.161168 | 1.408892 | -2.871940 | -1.083954 | -0.614166 | |
Loss of control in flight | 0 | 19.721178 | -80.587797 | 36.090635 | 20.597552 | 4.178432 |
1 | -19.721178 | 80.587797 | -36.090635 | -20.597552 | -4.178432 | |
Loss of control on ground | 0 | -83.986165 | 111.842143 | -24.983505 | -4.546825 | 1.674353 |
1 | 83.986165 | -111.842143 | 24.983505 | 4.546825 | -1.674353 | |
Turbulence encounter | 0 | 54.640771 | -54.730164 | 0.199894 | 0.792775 | -0.903275 |
1 | -54.640771 | 54.730164 | -0.199894 | -0.792775 | 0.903275 | |
Ground collision | 0 | 7.663238 | 2.133144 | -14.683576 | 3.370581 | 1.516613 |
1 | -7.663238 | -2.133144 | 14.683576 | -3.370581 | -1.516613 |
[20]:
severity_dict = {5:'Catastrophic Impact', 4:'Hazardous Impact', 3:'Major Impact', 2:'Minor Impact', 1:'Minimal Impact'}
rm_severities = {hazard: severity_dict[round(total_severities_hazard[hazard])] for hazard in total_severities_hazard}
rates = {hazard: sum([frequency_set[hazard][year] for year in frequency_set[hazard]])/len(years_of_interest) for hazard in frequency_set}
rm_likelihoods = get_likelihood_FAA(rates)
[21]:
mpl.rcParams.update(mpl.rcParamsDefault)
plt.rcParams["font.family"] = "Times New Roman"
[22]:
plot_risk_matrix(rm_likelihoods, rm_severities, figsize=(8,4), fontsize=12, max_chars=20, annot_font=10)
