Source code for mdf_reader.common.plots

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Apr 11 13:45:38 2019

Look into validation results

Need to type:
    
    %matplotlib auto

if ipython and want to get the interactive plots!


@author: iregon
"""

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

from .. import properties

#------------------------------------------------------------------------------
[docs]def plot_numeric_validation(data,mask,element,valid_max,valid_min, units): bbox_props = dict(boxstyle="round", fc="w", ec="0.5", alpha=0.9) plt.figure() ax = data.plot(label = 'data') # Carefull, something may not be working here in the no data tag!!! no_data = True if len(data.loc[data.notna()]) == 0 else False data.where(~mask).plot(marker = 'o',color = 'r',ax=ax,label='not valid') true_value = data.where(mask).median() if not true_value or np.isnan(true_value): if valid_max != None and valid_min != None: true_value = valid_min + (valid_max - valid_min)/2. else: true_value = 1 falses = pd.Series(index = data.index, data = true_value) falses.where(~mask & data.isna()).plot(marker = 'o',color = 'r',ax=ax,label='_nolegend_') trues = pd.Series(index = data.index,data = true_value ) trues.where(mask).plot(color = 'YellowGreen',ax=ax,label='valid') if valid_max != None and valid_min != None: ax.fill_between(data.index, valid_min,valid_max, facecolor='DarkSlateGrey', alpha=0.25, interpolate=False, label='valid range',zorder=5) ax.grid(linestyle=':',which='major',color='grey') if units: ax.set_ylabel(units, fontsize=10) ax.set_xlabel('idx') if no_data: ax.text((ax.get_xlim()[1] - ax.get_xlim()[0])/2,ax.get_ylim()[0] + (ax.get_ylim()[1] - ax.get_ylim()[0])/2, "no data", ha="center", va="center", size=20,bbox=bbox_props) plt.legend() plt.title(element + ' validation') plt.show()
[docs]def plot_categorical_validation(data,mask,element,codetable): merged = pd.concat([data,mask],axis = 1) merged.columns = ['data','mask'] counts = pd.DataFrame(index =merged['data'].value_counts(dropna = False).sort_index().index ) counts['Data'] = merged['data'].value_counts(dropna = False).sort_index() # Watch here, need to convert to str so that NaNs are not removed from the grouping! # Could be dangerous if we are not just counting, but then, we would not need the NaNs... counts.index = counts.index.fillna(str(np.nan)) counts['Not valid'] = merged.astype(str).query('mask == "False"').groupby('data').count() counts['Valid'] = merged.astype(str).query('mask == "True"').groupby('data').count() fig = plt.figure() # Create matplotlib figure ax = fig.add_subplot(111) # Create matplotlib axes ax2 = ax.twinx() # Create another axes that shares the same x-axis as ax. width = 0.4 counts['Data'].plot(kind='bar', ax=ax, width=width, position=1, color = 'DarkCyan', label = 'data counts') counts[['Not valid','Valid']].plot(kind='bar', stacked=True, ax=ax2, width=width, position=0,legend = False, color = ['DarkRed','YellowGreen']) ax.set_yscale("log") ax.set_ylabel('data counts', fontsize=10) ax2.set_yscale("log") ax2.set_ylabel('validation counts', fontsize=10) ax.legend(loc = 2) ax2.legend() ax.grid(linestyle=':',which='major',color='grey') plt.title(element + " validation \n Codetable: " + codetable) ax.set_xlim(-1,len(counts)) ax.set_xlabel('code') ax2.set_xlim(-1,len(counts)) ax.set_ylim(0.5,ax.get_ylim()[1]) ax2.set_ylim(0.5,ax2.get_ylim()[1]) plt.show()
#------------------------------------------------------------------------------
[docs]def plot_model_validation(imodel): for element in imodel['atts'].keys(): title_element = element if not isinstance(element,tuple) else element[1] + " (" + element[0] + ")" dtype = imodel['atts'].get(element).get('column_type') if dtype in properties.numeric_types: valid_max = imodel['atts'].get(element).get('valid_max') valid_min = imodel['atts'].get(element).get('valid_min') units = imodel['atts'].get(element).get('units') plot_numeric_validation(imodel['data'][element],imodel['valid_mask'][element],title_element, valid_max, valid_min, units) elif dtype == 'key': # ...mmm should account for multi-keyed combinations codetable = imodel['atts'].get(element).get('codetable') if not codetable: codetable = 'undefined' plot_categorical_validation(imodel['data'][element],imodel['valid_mask'][element],title_element,codetable)