pyMez.Code.Analysis.Reports module
Reports is a module dedicated to generating reports after data collection or analysis. It contains models for basic html reports and the checkstandard reporting process.
Examples
>>report=HTMLReport() >>report.embedd_image("my.png",image_mode="PngFile") >>report.show()
Requirements
Help
#----------------------------------------------------------------------------- # Name: Reports # Purpose: # Author: Aric Sanders # Created: 1/26/2018 # License: MIT License #----------------------------------------------------------------------------- """Reports is a module dedicated to generating reports after data collection or analysis. It contains models for basic html reports and the checkstandard reporting process. Examples -------- #!python >>report=HTMLReport() >>report.embedd_image("my.png",image_mode="PngFile") >>report.show() Requirements ------------ + [sys](https://docs.python.org/2/library/sys.html) + [os](https://docs.python.org/2/library/os.html) + [re](https://docs.python.org/2/library/re.html) + [math](https://docs.python.org/2/library/math.html) + [pyMez](https://github.com/aricsanders/pyMez) Help --------------- <a href="./index.html">`pyMez.Code.Analysis`</a> <div> <a href="../../../pyMez_Documentation.html">Documentation Home</a> | <a href="../../index.html">API Documentation Home</a> | <a href="../../../Examples/html/Examples_Home.html">Examples Home</a> | <a href="../../../Reference_Index.html">Index</a> </div> """ #----------------------------------------------------------------------------- # Standard Imports import os import sys import math import re #----------------------------------------------------------------------------- # Third Party Imports sys.path.append(os.path.join(os.path.dirname( __file__ ), '..','..')) try: from Code.Analysis.SParameter import * except: print("Code.Analysis.SParameter did not import correctly") raise ImportError try: from Code.Analysis.Uncertainty import * except: print("Code.Analysis.Uncertainty did not import correctly") raise ImportError try: from Code.DataHandlers.NISTModels import * except: print("Code.DataHandlers.NISTModels did not import correctly") raise ImportError try: from Code.DataHandlers.XMLModels import * except: print("Code.DataHandlers.XMLModels did not import correctly") raise ImportError try: from Code.DataHandlers.HTMLModels import * except: print("Code.DataHandlers.HTMLModels did not import correctly") raise ImportError try: from Code.DataHandlers.GraphModels import * except: print("Code.DataHandlers.GraphModels did not import correctly") raise ImportError try: from bokeh.plotting import figure from bokeh.embed import components except: pass #----------------------------------------------------------------------------- # Module Constants TWO_PORT_NR_CHKSTD_CSV=r"C:\Share\Converted_Check_Standard\Two_Port_NR_Check_Standard.csv" COMBINED_ONE_PORT_CHKSTD_CSV=r"C:\Share\Converted_Check_Standard\Combined_One_Port_Check_Standard.csv" COMBINED_TWO_PORT_CHKSTD_CSV=r"C:\Share\Converted_Check_Standard\Combined_Two_Port_Check_Standard.csv" COMBINED_POWER_CHKSTD_CSV=r"C:\Share\Converted_Check_Standard\Combined_Power_Check_Standard.csv" ONE_PORT_CALREP_CSV=r"C:\Share\Converted_DUT\One_Port_DUT.csv" TWO_PORT_CALREP_CSV=r"C:\Share\Converted_DUT\Two_Port_DUT.csv" POWER_3TERM_CALREP_CSV=r"C:\Share\Converted_DUT\Power_3Term_DUT.csv" POWER_4TERM_CALREP_CSV=r"C:\Share\Converted_DUT\Power_4Term_DUT.csv" DEFAULT_TOGGLE_SCRIPT="""<script type="text/javascript"> function toggleId(id,$link){ $node = document.getElementById(id); if (!$node) return; if (!$node.style.display || $node.style.display == 'none') { $node.style.display = 'block'; $link.value = '-'; } else { $node.style.display = 'none'; $link.value = '+'; } } </script>""" DEFAULT_TOGGLE_STYLE="""<style> .toggleButton { background-color: white; border: 2px solid black; border-radius: 8px; color:red; } .toggleButton:hover { box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19); } </stlye>""" ONE_PORT_DTYPE={'Frequency':'float', 'Direction':'str', 'Connect':'str', 'System_Id':'str', 'System_Letter':'str', 'Connector_Type_Calibration':'str', 'Connector_Type_Measurement':'str', 'Measurement_Type':'str', 'Measurement_Date':'str', 'Measurement_Time':'str', 'Program_Used':'str', 'Program_Revision':'str', 'Operator':'str', 'Calibration_Name':'str', 'Calibration_Date':'str', 'Port_Used':'int', 'Number_Connects':'str', 'Number_Repeats':'str', 'Nbs':'str', 'Number_Frequencies':'str', 'Start_Frequency':'float', 'Device_Description':'str', 'Device_Id':'str', 'Measurement_Timestamp':'str', } #----------------------------------------------------------------------------- # Module Functions def bokeh_parse_format_string(format_string): """Returns a string with color and a list with string styles [color,[style1,style2..]]to be given to bokeh plot""" style_dictionary={"*":"asterisk", "o":"circle", "o+":"circle_cross", "ox":"circle_x", "+":"cross", "--":"dash", "d":"diamond", "d+":"diamond_cross", "v":"inverted_triangle", "sq":"square", "sq+":"square_cross", "sqx":"square_x", "^":"triangle", "x":"x", "-":"line"} color_dictionary={"r":"red", "b":"blue", "k":"black", "w":"white", "g":"green", "c":"cyan", "m":"magenta", "y":"yellow"} remaining_code=format_string color="blue" for color_code in color_dictionary.keys(): if re.match(color_code,remaining_code): color=color_dictionary[color_code] remaining_code=remaining_code.replace(color_code,"") styles=[] if "--" in remaining_code: style="dash" styles.append(style) remaining_code=remaining_code.replace("--","") i=0 sorted_style_keys=sorted(style_dictionary.keys())[::-1] while ((remaining_code!="") or (i<len(style_dictionary.keys())-1)): style_key=sorted_style_keys[i] if re.search(re.escape(style_key),remaining_code): styles.append(style_dictionary[style_key]) remaining_code=remaining_code.replace(style_key,"") i+=1 return [color,styles] #----------------------------------------------------------------------------- # Module Classes class HTMLReport(HTMLBase): def add_toggle_script(self, script=DEFAULT_TOGGLE_SCRIPT): """Adds a javascript template toggle script to the body of the HTML""" self.append_to_body(script) def add_toggle_style(self, style=DEFAULT_TOGGLE_STYLE): """Adds a css to format the javascript template, should be done once""" self.append_to_head(style) def add_toggle(self, tag_id=None): """Adds a toggle button that toggles the element with id tag_id. This can be used many times """ toggle = '<input type="button" class="toggleButton" value="+" onclick="toggleId(\'{0}\',this)">'.format(tag_id) self.append_to_body(toggle) def embedd_image(self, image, image_mode="MatplotlibFigure", **options): """Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values""" # might change this to self.ImageGraph and use it elsewhere image_graph = ImageGraph() image_graph.set_state(image_mode, image) image_graph.move_to_node("EmbeddedHtml") self.append_to_body(image_graph.data) def embedd_image_figure(self, image, image_mode="MatplotlibFigure", figure_id="image", caption="", style="", **options): """Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values. The image is in a <figure id=figure_id> tag""" # might change this to self.ImageGraph and use it elsewhere image_graph = ImageGraph() image_graph.set_state(image_mode, image) image_graph.move_to_node("EmbeddedHtml") self.append_to_body("<figure id='{0}' style='{3}'>{1}<figcaption>{2}</figcaption></figure>".format(figure_id, image_graph.data, caption, style)) def add_download_link(self, content_string, text="Download File", suggested_name="test.txt", mime_type="text/plain"): """Adds a download link to the report""" self.append_to_body(String_to_DownloadLink(content_string, text=text, suggested_name=suggested_name, mime_type=mime_type)) def clear(self): """Clears all content in the HTML""" element_list = self.root.getchildren() for child in element_list: self.root.remove(child) class BokehReport(HTMLReport): def __init__(self): self.cdn_script_string = """<script src="https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.js"></script>""" self.cdn_css_string = """<link href="https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.css" rel="stylesheet" type="text/css">""" HTMLReport.__init__(self) self.add_head() self.add_body() self.append_to_head(self.cdn_css_string) self.append_to_head(self.cdn_script_string) self.figures = [] self.div_elements = [] self.script_elements = [] def plot(self, x_data, y_data, format="", **options): """Creates an interactive plot using bokeh and appends to the body""" defaults = {"tools": "pan,box_zoom,reset,save", "title": None, "plot_width": 400, "plot_height": 400, "styles": ["line"], "color": "gray", "figure_index": False, "glyph_options": {}} self.plot_options = {} for key, value in defaults.items(): self.plot_options[key] = value for key, value in options.items(): self.plot_options[key] = value figure_option_keys = ["tools", "title", "plot_width", "plot_height", "active_drag", "active_inspect", "active_scroll", "active_tap", "tooltips"] figure_options = {} for key in self.plot_options.keys(): if key in figure_option_keys: figure_options[key] = self.plot_options[key] if self.plot_options["figure_index"] is not False: plot = self.figures[self.plot_options["figure_index"]] else: plot = figure(**figure_options) self.figures.append(plot) if format: [color, styles] = bokeh_parse_format_string(format) else: [color, styles] = [self.plot_options["color"], self.plot_options["styles"]] for style in styles: if style in ["line"]: plotter = getattr(plot, style) plotter(x_data, y_data, line_color=color, **self.plot_options["glyph_options"]) elif style is "dash": plot.line(x_data, y_data, line_dash="dashed") else: plotter = getattr(plot, style) plotter(x_data, y_data, fill_color=color, line_color=color, **self.plot_options["glyph_options"]) script, div = components(plot) if self.plot_options["figure_index"] is not False: figure_index = self.plot_options["figure_index"] self.root.head.remove(self.script_elements[figure_index]) self.append_to_head(str(script)) self.script_elements[figure_index] = self.root.head.getchildren()[-1] new_div_element = lxml.etree.fromstring(str(div)) self.div_elements[figure_index].attrib["id"] = new_div_element.attrib["id"] else: self.append_to_head(str(script)) self.append_to_body(str(div)) self.div_elements.append(self.root.body.getchildren()[-1]) self.script_elements.append(self.root.head.getchildren()[-1]) class CheckStandardReport(HTMLReport): """Class that creates a report based on a calibrated measurement of a checkstandard. Input can be a file path to any of the ascii data types returned by the modified measlp program or a multiconnect mulitdirectional set of measurements in magnitude / angle format. The locations of the CheckStandard data bases in csv format and the directory of the results files are required. The report is composed of: 1. A plot of the raw file 2. A plot of the file with calrep style errors 3. A plot comparing the file with calrep style errors to the old results database 4. A plot comparing the difference of the file to the old results database 5. A plot comparing the file with calrep style errors to the mean of the new database with outliers excluded 6. A history plot of the check standard for the current measurement and the last n measurements (default is 5) 7. A complete history plot of the check standard 8. A set of download links in text and the formats set in options If no file is specified and a checkstandard_name is, then only history and means of that checkstandard are shown in the report""" def __init__(self, file_path=None, **options): """Initializes the CheckStandardReport Class""" defaults = {"Device_Id": "CTN112", "results_directory": r'C:\Share\resfiles', "one_port_csv": COMBINED_ONE_PORT_CHKSTD_CSV, "two_port_csv": COMBINED_TWO_PORT_CHKSTD_CSV, "two_port_nr_csv": TWO_PORT_NR_CHKSTD_CSV, "power_csv": COMBINED_POWER_CHKSTD_CSV, "outlier_removal": True, "last_n": 5, "download_formats": ["Csv"], "conversion_options":{ "nodes": ['CsvFile', 'ExcelFile'], "extensions": [ 'csv', 'xlsx'], "mime_types": ['text/plain', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']} } self.options = {} for key, value in defaults.items(): self.options[key] = value for key, value in options.items(): self.options[key] = value self.conversion_defaults = {"base_name": None, "nodes": ['XmlFile', 'CsvFile', 'ExcelFile', 'OdsFile', 'MatFile', 'HtmlFile', 'JsonFile'], "extensions": ['xml', 'csv', 'xlsx', 'ods', 'mat', 'html', 'json'], "mime_types": ['application/xml', 'text/plain', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.oasis.opendocument.spreadsheet', 'application/x-matlab-data', 'text/html', 'application/json']} # html_options={} if self.options["conversion_options"] is None: self.conversion_options=self.conversion_defaults else: self.conversion_options=self.options["conversion_options"] HTMLReport.__init__(self, None, **self.options) self.plots = [] self.plot_ids = [] self.plot_titles = [] self.plot_captions = [] # set up dtypes for pandas one_port_dtype = ONE_PORT_DTYPE # this reads the NISTModels constant if COMBINE_S11_S22: one_port_dtype["arg"] = 'float' one_port_dtype["mag"] = 'float' else: one_port_dtype["argS11"] = 'float' one_port_dtype["magS11"] = 'float' one_port_dtype["argS22"] = 'float' one_port_dtype["magS22"] = 'float' # create a history dictionary. # print("{0} is {1}".format("self.options",self.options)) self.history_dict = {'1-port': pandas.read_csv(self.options["one_port_csv"], dtype=one_port_dtype), '2-port': pandas.read_csv(self.options["two_port_csv"]), '2-portNR': pandas.read_csv(self.options["two_port_nr_csv"]), 'power': pandas.read_csv(self.options["power_csv"])} if file_path is None: # plot the results file self.build_checkstandard_report() else: self.build_comparison_report(file_path) def build_checkstandard_report(self): """Builds the report for the options Device_Id""" self.raw_measurement=None self.calrep_measurement=None self.clear() self.plots = [] self.plot_ids = [] self.plot_captions = [] self.plot_titles = [] measurement_type = self.options["Device_Id"][-3] if re.match("1", measurement_type): self.options["Measurement_Type"] = "1-port" elif re.match("2", measurement_type): self.options["Measurement_Type"] = "2-port" elif re.match("p", measurement_type, re.IGNORECASE): self.options["Measurement_Type"] = "power" print(("{0} is {1}".format("measurement_type",measurement_type))) try: self.results_file = ResultFileModel(os.path.join(self.options["results_directory"], self.options["Device_Id"])) except: self.results_file=ResultFileModel(None) options = {"Device_Id": self.options["Device_Id"], "System_Id": None, "Measurement_Timestamp": None, "Connector_Type_Measurement": None, "Measurement_Date": None, "Measurement_Time": None, "outlier_removal": False} if re.search('2-port', self.options["Measurement_Type"], re.IGNORECASE): history_key = '2-port' options["column_names"] = ['Frequency', 'magS11', 'argS11', 'magS21', 'argS21', 'magS22', 'argS22'] elif re.search('1-port', self.options["Measurement_Type"], re.IGNORECASE): history_key = '1-port' if COMBINE_S11_S22: options["column_names"] = ['Frequency', 'magS11', 'argS11'] else: options["column_names"] = ['Frequency', 'magS11', 'argS11', 'magS22', 'argS22'] elif re.search('Dry Cal|Thermistor|power', self.options["Measurement_Type"], re.IGNORECASE): history_key = 'power' options["column_names"] = ['Frequency', 'magS11', 'argS11', 'Efficiency'] # print history[history_key][:5] # print history_key database = self.history_dict[history_key] self.device_history = database[database["Device_Id"] == self.options["Device_Id"]] if self.options["outlier_removal"]: self.outlier_removal() self.mean_frame = mean_from_history(self.device_history, **options) self.plots.append(plot_checkstandard_history(self.device_history)) self.plot_ids.append("completeHistory") self.plot_titles.append("The Complete History of {0}".format(self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Every measurement of {1} currently in the database.""".format(len(self.plots), self.options["Device_Id"])) self.plots.append(plot_checkstandard_history(self.device_history, min_num=len(self.get_measurement_dates()) - self.options[ "last_n"] - 1, max_num=len(self.get_measurement_dates()) - 1, extra_plots=[self.results_file, self.mean_frame], extra_plot_labels=["Historical Database", "Mean of New Database"], extra_plot_formats=["r--", "k^"])) self.plot_ids.append("partialHistory") self.plot_titles.append("""The last {0} measurements of {1} compared with the historical database and mean. """.format(self.options["last_n"], self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Last {1} measurements of {2} compared with historical database and mean""".format(len(self.plots), self.options["last_n"], self.options["Device_Id"])) self.add_toggle_support() summary_text = """ This device has been measured {0} times from {1} to {2}""".format(len(self.get_measurement_dates()), min(self.get_measurement_dates()), max(self.get_measurement_dates())) self.add_report_heading() self.append_to_body({"tag": "p", "text": summary_text}) download_options={"mime_types":self.conversion_options["mime_types"], "download_formats":self.conversion_options["nodes"], "download_extensions":self.conversion_options["extensions"], "clear_before": False, "download_files": [self.results_file, self.mean_frame, self.device_history], "download_files_input_format": ["AsciiDataTable", "DataFrame", "DataFrame"], "download_files_base_names": ["Historical_Database.txt", "Mean_Database.txt", "Device_History.txt"], "style": "display:none;border:1;"} self.add_download_table(**download_options) self.add_all_plots() def build_comparison_report(self, raw_file_path=None): """Builds the report for a raw file comparison, requires a raw_file_path to process""" self.clear() self.plots = [] self.plot_ids = [] self.plot_captions = [] self.plot_titles = [] self.raw_measurement_model = sparameter_power_type(raw_file_path) self.raw_measurement = globals()[self.raw_measurement_model](raw_file_path) # print("{0} is {1}".format("self.raw_measurement.column_names",self.raw_measurement.column_names)) table = self.raw_measurement self.options["Device_Id"] = table.metadata["Device_Id"] self.plots.append(self.raw_measurement.show()) self.plot_ids.append("rawMeasurement") self.plot_titles.append("Raw Measurement of {0}".format(self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Raw measurement of {1}. The measurement of check standard {1} in a calibrated mode.""".format(len(self.plots), self.options["Device_Id"])) self.calrep_measurement = calrep(self.raw_measurement) self.plots.append(plot_calrep(self.calrep_measurement)) self.plot_ids.append("clarepMeasurement") self.plot_titles.append("Plot of {0} with uncertainty".format(self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Measurement of {1}. The measurement of check standard {1} with nist total uncertainty.""".format(len(self.plots), self.options["Device_Id"])) self.plots.append(plot_calrep_uncertainty(self.calrep_measurement)) self.plot_ids.append("clarepUncert") self.plot_titles.append("Plot Uncertainty Components".format(self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Uncertainty Components. The uncertainty in measurement of check standard {1} .""".format(len(self.plots), self.options["Device_Id"])) try: self.results_file = ResultFileModel(os.path.join(self.options["results_directory"], self.calrep_measurement.metadata["Device_Id"])) except: self.results_file = None options = {"Device_Id": table.metadata["Device_Id"], "System_Id": table.metadata["System_Id"], "Measurement_Timestamp": None, "Connector_Type_Measurement": table.metadata["Connector_Type_Measurement"], "Measurement_Date": None, "Measurement_Time": None, "outlier_removal": False} if re.search('2-port', table.metadata["Measurement_Type"], re.IGNORECASE) and not re.search('2-portNR', table.metadata["Measurement_Type"], re.IGNORECASE): history_key = '2-port' options["column_names"] = ['Frequency', 'magS11', 'argS11', 'magS21', 'argS21', 'magS22', 'argS22'] elif re.search('2-portNR', table.metadata["Measurement_Type"], re.IGNORECASE): history_key = '2-portNR' options["column_names"] = ['Frequency', 'magS11', 'argS11', 'magS12', 'argS12', 'magS21', 'argS21', 'magS22', 'argS22'] elif re.search('1-port', table.metadata["Measurement_Type"], re.IGNORECASE): history_key = '1-port' if COMBINE_S11_S22: options["column_names"] = ['Frequency', 'magS11', 'argS11'] else: options["column_names"] = ['Frequency', 'magS11', 'argS11', 'magS22', 'argS22'] elif re.search('Dry Cal|Thermistor|power', table.metadata["Measurement_Type"], re.IGNORECASE): history_key = 'power' options["column_names"] = ['Frequency', 'magS11', 'argS11', 'Efficiency'] # print history[history_key][:5] # print history_key database = self.history_dict[history_key] self.device_history = database[database["Device_Id"] == self.options["Device_Id"]] if self.options["outlier_removal"]: self.outlier_removal() self.mean_frame = mean_from_history(self.device_history.copy(), **options) # print mean_frame self.difference_frame = raw_difference_frame(table, self.mean_frame) # print("{0} is {1}".format("self.raw_measurement.column_names",self.raw_measurement.column_names)) # print difference_frame self.plots.append(raw_comparison_plot_with_residuals(table, self.mean_frame, self.difference_frame)) self.plot_ids.append("rawSummary") self.plot_titles.append("Summary of Measurement and Mean of Complete Database with Resisduals") self.plot_captions.append("""Figure {0}. Summary of Measurement and Mean with Resisduals. Data for all measurements are being used""".format(len(self.plots))) # stop_time=datetime.datetime.now() # diff=stop_time-start_time self.plots.append(plot_calrep_results_comparison(self.calrep_measurement, self.results_file, display_legend=True)) self.plot_ids.append("compareWithUncertainty") self.plot_titles.append("Measurement with Uncertainties compared with Historical Database") self.plot_captions.append("""Figure {0}. Measurement with Uncertainties compared with Historical Database. This is the current selection criteria""".format(len(self.plots))) self.plots.append(plot_calrep_results_difference_comparison(self.calrep_measurement, self.results_file, display_legend=True)) self.plot_ids.append("compareWithUncertaintyDifference") self.plot_titles.append("The Difference of Measurement with Uncertainties compared with Historical Database") self.plot_captions.append("""Figure {0}. The Difference of Measurement with Uncertainties compared with Historical Database. This is the current selection criteria.""".format(len(self.plots))) column_names = return_calrep_value_column_names(self.calrep_measurement) error_column_names = return_calrep_error_column_names(column_names) self.standard_error = standard_error_data_table(self.calrep_measurement, self.results_file, table_1_uncertainty_column_names=error_column_names, value_column_names=column_names, expansion_factor=1) number_columns_pass = list(self.standard_error.get_conformation_dictionary().values()).count(True) number_columns = len(list(self.standard_error.get_conformation_dictionary().values())) good = int(round(float(number_columns_pass - 1) / float(number_columns - 1))) pass_fail = "" if good: pass_fail = "PASSES" else: pass_fail = "FAILS" self.plots.append(self.standard_error.show()) self.plot_ids.append("standardErrror") self.plot_titles.append( "The Standard Error of Measurement with Uncertainties compared with Historical Database") self.plot_captions.append("""Figure {0}. The Standard Error of Measurement with Uncertainties compared with Historical Database. This is the current selection criteria.""".format(len(self.plots))) self.plots.append(plot_checkstandard_history(self.device_history)) self.plot_ids.append("completeHistory") self.plot_titles.append("The Complete History of {0}".format(self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Every measurement of {1} currently in the database.""".format(len(self.plots), self.options["Device_Id"])) self.plots.append(plot_checkstandard_history(self.device_history, min_num=len(self.get_measurement_dates()) - self.options[ "last_n"] - 1, max_num=len(self.get_measurement_dates()) - 1, extra_plots=[self.results_file, self.mean_frame], extra_plot_labels=["Historical Database", "Mean of New Database"], extra_plot_formats=["r--", "k^"])) self.plot_ids.append("partialHistory") self.plot_titles.append("""The last {0} measurements of {1} compared with the historical database and mean. """.format(self.options["last_n"], self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Last {1} measurements of {2} compared with historical database and mean""".format(len(self.plots), self.options["last_n"], self.options["Device_Id"])) self.add_toggle_support() summary_text = """This is a summary of the measurement of {0} made on {1} by {2}. This measurement {3} the checkstandard process. This device has been measured {4} times from {5} to {6}""".format(self.options["Device_Id"], self.raw_measurement.metadata[ "Measurement_Date"], self.raw_measurement.metadata["Operator"], pass_fail, len(self.get_measurement_dates()), min(self.get_measurement_dates()), max(self.get_measurement_dates())) self.add_report_heading() self.append_to_body({"tag": "p", "text": summary_text}) self.add_download_table(download_extensions=self.conversion_options["extensions"], download_formats=self.conversion_options["nodes"], mime_types=self.conversion_options["mime_types"]) self.add_table_border_style() self.add_metadata_section() self.add_all_plots() def get_measurement_dates(self): """Returns measurement dates from self.device_history""" dates = sorted(self.device_history["Measurement_Timestamp"].unique()) self.measurement_dates = dates[:] return dates def outlier_removal(self): """Removes outliers frome self.device_history""" mean_s11 = np.mean(self.device_history["magS11"]) std_s11 = np.std(self.device_history["magS11"]) self.device_history = self.device_history[self.device_history["magS11"] < (mean_s11 + 3 * std_s11)] self.device_history = self.device_history[self.device_history["magS11"] > (mean_s11 - 3 * std_s11)] def add_all_plots(self, **options): """Adds all plots in the attribute self.plots""" defaults = {"clear_before": False, "style": "display:none", "figure_width": 14} add_options = {} for key, value in defaults.items(): add_options[key] = value for key, value in options.items(): add_optionss[key] = value if add_options["clear_before"]: self.clear() for index, plot in enumerate(self.plots): id_text = self.plot_ids[index] self.append_to_body({"tag": "hr"}) self.append_to_body({"tag": "h2", "text": self.plot_titles[index]}) self.add_toggle(id_text) plot.set_figwidth(add_options["figure_width"]) self.embedd_image_figure(plot, figure_id="{0}".format(id_text), style=add_options["style"], caption=self.plot_captions[index]) self.append_to_body({"tag": "hr"}) def add_report_heading(self, heading_text=None, **options): """Adds a heading to the report, clears the report by default""" defaults = {"clear_before": False} add_options = {} for key, value in defaults.items(): add_options[key] = value for key, value in options.items(): add_options[key] = value if add_options["clear_before"]: self.clear() if heading_text is None: heading_text = "Check Standard Report for {0}".format(self.options["Device_Id"]) self.append_to_body({"tag": "h1", "text": heading_text}) def add_toggle_support(self): """Adds a toggle style and script to the report""" self.add_toggle_script() self.add_toggle_style() def add_download_table(self, download_formats=["CsvFile", "ExcelFile"], download_extensions=["csv", "xlsx"], mime_types=["text/plain", 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], **options): """Adds a table of downloadable files""" defaults = {"clear_before": False, "download_files": [self.raw_measurement, self.calrep_measurement, self.results_file, self.mean_frame, self.device_history], "download_files_input_format": ["AsciiDataTable", "AsciiDataTable", "AsciiDataTable", "DataFrame", "DataFrame"], "download_files_base_names": ["Raw_Measurement.txt", "Measurement_NIST_Uncertainties.txt", "Historical_Database.txt", "Mean_Database.txt", "Device_History.txt"], "style": "display:none;border:1;"} add_options = {} for key, value in defaults.items(): add_options[key] = value for key, value in options.items(): add_options[key] = value if add_options["clear_before"]: self.clear() self.append_to_body({"tag": "h2", "text": "Downloads"}) self.add_toggle("downloads") table_graph = TableGraph() # convert all data to AsciiDataTable format download_table = "<table id='downloads' style='{0}'>".format(add_options["style"]) for index, download in enumerate(add_options["download_files"][:]): if add_options["download_files_input_format"][index] not in ["AsciiDataTable"]: table_graph.set_state(add_options["download_files_input_format"][index], download) table_graph.move_to_node("AsciiDataTable") download = table_graph.data.copy() # now we cycle throught the download formats, for each file we load the graph and then create the download links ascii_download = String_to_DownloadLink(string=str(download), mime_type="text/plain", suggested_name=add_options["download_files_base_names"][index], text=add_options["download_files_base_names"][index]) #print(("{0} is {1}".format("index", index))) table_graph.set_state("AsciiDataTable", download) download_links = TableGraph_to_Links(table_graph, base_name=add_options["download_files_base_names"][index], nodes=download_formats, extensions=download_extensions, mime_types=mime_types) download_table = download_table + "<tr><td>{0}</td><td>{1}</td></tr>".format(ascii_download, download_links) download_table = download_table + "</table>" self.append_to_body(download_table) self.append_to_body({"tag": "hr"}) def add_metadata_section(self, style="display:none;border: 1px solid black;"): """Adds a metadata section if self.raw_measurement exits""" try: self.append_to_body({"tag": "h2", "text": "Measurement Metadata"}) self.add_toggle("metadata") self.append_to_body({"tag": "hr"}) meta_table = "<table id='metadata' style='{0}'>".format(style) for key, value in self.raw_measurement.metadata.items(): meta_table = meta_table + "<tr><td>{0}</td><td>{1}</td></tr>".format(key, value) meta_table = meta_table + "</table>" self.append_to_body(meta_table) except: pass def add_table_border_style(self): """Adds a css style tag to the head of the sheet to display all borders""" self.append_to_head({"tag": "style", "text": """table, th, td { border: 1px solid black;}"""}) #----------------------------------------------------------------------------- # Module Scripts def test_CheckStandardReport(raw_file_path=os.path.join(TESTS_DIRECTORY,'CTN208.R1_062614')): """Tests the checkstandard report class""" report=CheckStandardReport(raw_file_path) report.show() #----------------------------------------------------------------------------- # Module Runner if __name__ == '__main__': test_CheckStandardReport()
Functions
def bokeh_parse_format_string(
format_string)
Returns a string with color and a list with string styles [color,[style1,style2..]]to be given to bokeh plot
def bokeh_parse_format_string(format_string): """Returns a string with color and a list with string styles [color,[style1,style2..]]to be given to bokeh plot""" style_dictionary={"*":"asterisk", "o":"circle", "o+":"circle_cross", "ox":"circle_x", "+":"cross", "--":"dash", "d":"diamond", "d+":"diamond_cross", "v":"inverted_triangle", "sq":"square", "sq+":"square_cross", "sqx":"square_x", "^":"triangle", "x":"x", "-":"line"} color_dictionary={"r":"red", "b":"blue", "k":"black", "w":"white", "g":"green", "c":"cyan", "m":"magenta", "y":"yellow"} remaining_code=format_string color="blue" for color_code in color_dictionary.keys(): if re.match(color_code,remaining_code): color=color_dictionary[color_code] remaining_code=remaining_code.replace(color_code,"") styles=[] if "--" in remaining_code: style="dash" styles.append(style) remaining_code=remaining_code.replace("--","") i=0 sorted_style_keys=sorted(style_dictionary.keys())[::-1] while ((remaining_code!="") or (i<len(style_dictionary.keys())-1)): style_key=sorted_style_keys[i] if re.search(re.escape(style_key),remaining_code): styles.append(style_dictionary[style_key]) remaining_code=remaining_code.replace(style_key,"") i+=1 return [color,styles]
def test_CheckStandardReport(
raw_file_path='C:\\ProgramData\\Anaconda2\\lib\\site-packages\\pyMez\\Code\\DataHandlers\\Tests\\CTN208.R1_062614')
Tests the checkstandard report class
def test_CheckStandardReport(raw_file_path=os.path.join(TESTS_DIRECTORY,'CTN208.R1_062614')): """Tests the checkstandard report class""" report=CheckStandardReport(raw_file_path) report.show()
Classes
class BokehReport
class BokehReport(HTMLReport): def __init__(self): self.cdn_script_string = """<script src="https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.js"></script>""" self.cdn_css_string = """<link href="https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.css" rel="stylesheet" type="text/css">""" HTMLReport.__init__(self) self.add_head() self.add_body() self.append_to_head(self.cdn_css_string) self.append_to_head(self.cdn_script_string) self.figures = [] self.div_elements = [] self.script_elements = [] def plot(self, x_data, y_data, format="", **options): """Creates an interactive plot using bokeh and appends to the body""" defaults = {"tools": "pan,box_zoom,reset,save", "title": None, "plot_width": 400, "plot_height": 400, "styles": ["line"], "color": "gray", "figure_index": False, "glyph_options": {}} self.plot_options = {} for key, value in defaults.items(): self.plot_options[key] = value for key, value in options.items(): self.plot_options[key] = value figure_option_keys = ["tools", "title", "plot_width", "plot_height", "active_drag", "active_inspect", "active_scroll", "active_tap", "tooltips"] figure_options = {} for key in self.plot_options.keys(): if key in figure_option_keys: figure_options[key] = self.plot_options[key] if self.plot_options["figure_index"] is not False: plot = self.figures[self.plot_options["figure_index"]] else: plot = figure(**figure_options) self.figures.append(plot) if format: [color, styles] = bokeh_parse_format_string(format) else: [color, styles] = [self.plot_options["color"], self.plot_options["styles"]] for style in styles: if style in ["line"]: plotter = getattr(plot, style) plotter(x_data, y_data, line_color=color, **self.plot_options["glyph_options"]) elif style is "dash": plot.line(x_data, y_data, line_dash="dashed") else: plotter = getattr(plot, style) plotter(x_data, y_data, fill_color=color, line_color=color, **self.plot_options["glyph_options"]) script, div = components(plot) if self.plot_options["figure_index"] is not False: figure_index = self.plot_options["figure_index"] self.root.head.remove(self.script_elements[figure_index]) self.append_to_head(str(script)) self.script_elements[figure_index] = self.root.head.getchildren()[-1] new_div_element = lxml.etree.fromstring(str(div)) self.div_elements[figure_index].attrib["id"] = new_div_element.attrib["id"] else: self.append_to_head(str(script)) self.append_to_body(str(div)) self.div_elements.append(self.root.body.getchildren()[-1]) self.script_elements.append(self.root.head.getchildren()[-1])
Ancestors (in MRO)
- BokehReport
- HTMLReport
- Code.DataHandlers.HTMLModels.HTMLBase
- __builtin__.object
Instance variables
var cdn_css_string
var cdn_script_string
var div_elements
var figures
var script_elements
Methods
def __init__(
self)
Inheritance:
HTMLReport
.__init__
Intializes the HTMLBase Class
def __init__(self): self.cdn_script_string = """<script src="https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.js"></script>""" self.cdn_css_string = """<link href="https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.css" rel="stylesheet" type="text/css">""" HTMLReport.__init__(self) self.add_head() self.add_body() self.append_to_head(self.cdn_css_string) self.append_to_head(self.cdn_script_string) self.figures = [] self.div_elements = [] self.script_elements = []
def add_body(
self)
Inheritance:
HTMLReport
.add_body
Adds a body tag to the model if it does not exist
def add_body(self): """Adds a body tag to the model if it does not exist""" body=make_html_element(tag="body",text="") tags=[x.tag.lower() for x in self.root.getchildren()] if not "body" in tags: self.root.append(body) else: print("body already exists, tag was not added ") pass self.body=self.root.body
def add_download_link(
self, content_string, text='Download File', suggested_name='test.txt', mime_type='text/plain')
Inheritance:
HTMLReport
.add_download_link
Adds a download link to the report
def add_download_link(self, content_string, text="Download File", suggested_name="test.txt", mime_type="text/plain"): """Adds a download link to the report""" self.append_to_body(String_to_DownloadLink(content_string, text=text, suggested_name=suggested_name, mime_type=mime_type))
def add_head(
self)
Inheritance:
HTMLReport
.add_head
Adds a head tag to the model if it does not exist
def add_head(self): """Adds a head tag to the model if it does not exist""" head=make_html_element(tag="head",text="") if len(self.root.getchildren())==0: self.root.append(head) elif not re.match("head",self.root.getchildren()[0].tag,re.IGNORECASE) and len(self.root.getchildren())>0: self.root.insert(0,head) else: print("head already exists, tag was not added ") self.head=self.root.head
def add_toggle(
self, tag_id=None)
Inheritance:
HTMLReport
.add_toggle
Adds a toggle button that toggles the element with id tag_id. This can be used many times
def add_toggle(self, tag_id=None): """Adds a toggle button that toggles the element with id tag_id. This can be used many times """ toggle = '<input type="button" class="toggleButton" value="+" onclick="toggleId(\'{0}\',this)">'.format(tag_id) self.append_to_body(toggle)
def add_toggle_script(
self, script='<script type="text/javascript">\n function toggleId(id,$link){\n $node = document.getElementById(id);\n if (!$node)\n return;\n if (!$node.style.display || $node.style.display == \'none\') {\n $node.style.display = \'block\';\n $link.value = \'-\';\n } else {\n $node.style.display = \'none\';\n $link.value = \'+\';\n }\n }\n </script>')
Inheritance:
HTMLReport
.add_toggle_script
Adds a javascript template toggle script to the body of the HTML
def add_toggle_script(self, script=DEFAULT_TOGGLE_SCRIPT): """Adds a javascript template toggle script to the body of the HTML""" self.append_to_body(script)
def add_toggle_style(
self, style='<style>\n .toggleButton {\n background-color: white;\n border: 2px solid black;\n border-radius: 8px;\n color:red;\n\t }\n .toggleButton:hover {\n box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);\n\t}\n </stlye>')
Inheritance:
HTMLReport
.add_toggle_style
Adds a css to format the javascript template, should be done once
def add_toggle_style(self, style=DEFAULT_TOGGLE_STYLE): """Adds a css to format the javascript template, should be done once""" self.append_to_head(style)
def append_to_body(
self, element)
Inheritance:
HTMLReport
.append_to_body
Appends the element to the body of the model, if it is a string it parses first, if it is a dictionary it assumes it has the form {"tag":tag_name,"text":text_text, "attribute_dictionary":{"attribute_name":"attribute_value"}, and if it is a lxml.html.HtmlElement it appends it
def append_to_body(self,element): """Appends the element to the body of the model, if it is a string it parses first, if it is a dictionary it assumes it has the form {"tag":tag_name,"text":text_text, "attribute_dictionary":{"attribute_name":"attribute_value"}, and if it is a lxml.html.HtmlElement it appends it""" try: tags = [x.tag.lower() for x in self.root.getchildren()] if not "body" in tags: body = make_html_element(tag="body", text="") print("Body tag was not present adding it") self.root.append(body) if isinstance(element, StringType): new_element=lxml.html.fragment_fromstring(element) elif isinstance(element, DictionaryType): new_element=make_html_element(**element) elif isinstance(element,lxml.html.HtmlElement): new_element=element self.root.body.append(new_element) except: print(("Could not add {0} to body".format(element)))
def append_to_head(
self, element)
Inheritance:
HTMLReport
.append_to_head
Appends the element to the head of the model, if it is a string it parses first, if it is a dictionary it assumes it has the form {"tag":tag_name,"text":text_text, "attribute_dictionary":{"attribute_name":"attribute_value"}, and if it is a lxml.html.HtmlElement it appends it
def append_to_head(self,element): """Appends the element to the head of the model, if it is a string it parses first, if it is a dictionary it assumes it has the form {"tag":tag_name,"text":text_text, "attribute_dictionary":{"attribute_name":"attribute_value"}, and if it is a lxml.html.HtmlElement it appends it""" try: tags = [x.tag.lower() for x in self.root.getchildren()] if not "head" in tags: head = make_html_element(tag="head", text="") print("Head tag was not present adding it") self.root.insert(0,head) if isinstance(element, StringType): new_element=lxml.html.fragment_fromstring(element) elif isinstance(element, DictionaryType): new_element=make_html_element(**element) elif isinstance(element,lxml.html.HtmlElement): new_element=element self.root.head.append(new_element) except: print(("Could not add {0} to head".format(element)))
def clear(
self)
Inheritance:
HTMLReport
.clear
Clears all content in the HTML
def clear(self): """Clears all content in the HTML""" element_list = self.root.getchildren() for child in element_list: self.root.remove(child)
def embedd_image(
self, image, image_mode='MatplotlibFigure', **options)
Inheritance:
HTMLReport
.embedd_image
Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values
def embedd_image(self, image, image_mode="MatplotlibFigure", **options): """Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values""" # might change this to self.ImageGraph and use it elsewhere image_graph = ImageGraph() image_graph.set_state(image_mode, image) image_graph.move_to_node("EmbeddedHtml") self.append_to_body(image_graph.data)
def embedd_image_figure(
self, image, image_mode='MatplotlibFigure', figure_id='image', caption='', style='', **options)
Inheritance:
HTMLReport
.embedd_image_figure
Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values. The image is in a
def embedd_image_figure(self, image, image_mode="MatplotlibFigure", figure_id="image", caption="", style="", **options): """Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values. The image is in a <figure id=figure_id> tag""" # might change this to self.ImageGraph and use it elsewhere image_graph = ImageGraph() image_graph.set_state(image_mode, image) image_graph.move_to_node("EmbeddedHtml") self.append_to_body("<figure id='{0}' style='{3}'>{1}<figcaption>{2}</figcaption></figure>".format(figure_id, image_graph.data, caption, style))
def plot(
self, x_data, y_data, format='', **options)
Creates an interactive plot using bokeh and appends to the body
def plot(self, x_data, y_data, format="", **options): """Creates an interactive plot using bokeh and appends to the body""" defaults = {"tools": "pan,box_zoom,reset,save", "title": None, "plot_width": 400, "plot_height": 400, "styles": ["line"], "color": "gray", "figure_index": False, "glyph_options": {}} self.plot_options = {} for key, value in defaults.items(): self.plot_options[key] = value for key, value in options.items(): self.plot_options[key] = value figure_option_keys = ["tools", "title", "plot_width", "plot_height", "active_drag", "active_inspect", "active_scroll", "active_tap", "tooltips"] figure_options = {} for key in self.plot_options.keys(): if key in figure_option_keys: figure_options[key] = self.plot_options[key] if self.plot_options["figure_index"] is not False: plot = self.figures[self.plot_options["figure_index"]] else: plot = figure(**figure_options) self.figures.append(plot) if format: [color, styles] = bokeh_parse_format_string(format) else: [color, styles] = [self.plot_options["color"], self.plot_options["styles"]] for style in styles: if style in ["line"]: plotter = getattr(plot, style) plotter(x_data, y_data, line_color=color, **self.plot_options["glyph_options"]) elif style is "dash": plot.line(x_data, y_data, line_dash="dashed") else: plotter = getattr(plot, style) plotter(x_data, y_data, fill_color=color, line_color=color, **self.plot_options["glyph_options"]) script, div = components(plot) if self.plot_options["figure_index"] is not False: figure_index = self.plot_options["figure_index"] self.root.head.remove(self.script_elements[figure_index]) self.append_to_head(str(script)) self.script_elements[figure_index] = self.root.head.getchildren()[-1] new_div_element = lxml.etree.fromstring(str(div)) self.div_elements[figure_index].attrib["id"] = new_div_element.attrib["id"] else: self.append_to_head(str(script)) self.append_to_body(str(div)) self.div_elements.append(self.root.body.getchildren()[-1]) self.script_elements.append(self.root.head.getchildren()[-1])
def save(
self, file_path=None, **temp_options)
Inheritance:
HTMLReport
.save
Saves the html file, provide file path to save as, or temp_options
def save(self,file_path=None,**temp_options): """Saves the html file, provide file path to save as, or temp_options""" original_options=self.options.copy() for key,value in temp_options.items(): self.options[key]=value if file_path is None: file_path=self.path out_file=open(file_path,"w") out_file.write(str(self)) out_file.close() self.options=original_options return file_path
def show(
self)
Inheritance:
HTMLReport
.show
Saves html to a temp file and shows it in a browser
def show(self): """Saves html to a temp file and shows it in a browser""" lxml.html.open_in_browser(self.document)
def to_HTML(
self)
Inheritance:
HTMLReport
.to_HTML
Convenience function that echos the content updates the attribute self.text
def to_HTML(self): """Convenience function that echos the content updates the attribute self.text""" self.text=str(self) return str(self.text)
def to_pdf(
self, file_path=None, **options)
Inheritance:
HTMLReport
.to_pdf
Converts the file to a pdf and saves it at file_path. If file_path is None, it will auto name the resulting file to self.path with pdf as the extension
def to_pdf(self,file_path=None,**options): """Converts the file to a pdf and saves it at file_path. If file_path is None, it will auto name the resulting file to self.path with pdf as the extension""" #todo: add toc and other options in wkhtmltopdf if file_path is None: file_path=change_extension(self.path,"pdf") config = pdfkit.configuration(wkhtmltopdf=WKHTML_PATH) pdfkit.from_string(str(self),file_path,configuration=config) return file_path
class CheckStandardReport
Class that creates a report based on a calibrated measurement of a checkstandard. Input can be a file path to any of the ascii data types returned by the modified measlp program or a multiconnect mulitdirectional set of measurements in magnitude / angle format. The locations of the CheckStandard data bases in csv format and the directory of the results files are required. The report is composed of: 1. A plot of the raw file 2. A plot of the file with calrep style errors 3. A plot comparing the file with calrep style errors to the old results database 4. A plot comparing the difference of the file to the old results database 5. A plot comparing the file with calrep style errors to the mean of the new database with outliers excluded 6. A history plot of the check standard for the current measurement and the last n measurements (default is 5) 7. A complete history plot of the check standard 8. A set of download links in text and the formats set in options
If no file is specified and a checkstandard_name is, then only history and means of that checkstandard are shown in the report
class CheckStandardReport(HTMLReport): """Class that creates a report based on a calibrated measurement of a checkstandard. Input can be a file path to any of the ascii data types returned by the modified measlp program or a multiconnect mulitdirectional set of measurements in magnitude / angle format. The locations of the CheckStandard data bases in csv format and the directory of the results files are required. The report is composed of: 1. A plot of the raw file 2. A plot of the file with calrep style errors 3. A plot comparing the file with calrep style errors to the old results database 4. A plot comparing the difference of the file to the old results database 5. A plot comparing the file with calrep style errors to the mean of the new database with outliers excluded 6. A history plot of the check standard for the current measurement and the last n measurements (default is 5) 7. A complete history plot of the check standard 8. A set of download links in text and the formats set in options If no file is specified and a checkstandard_name is, then only history and means of that checkstandard are shown in the report""" def __init__(self, file_path=None, **options): """Initializes the CheckStandardReport Class""" defaults = {"Device_Id": "CTN112", "results_directory": r'C:\Share\resfiles', "one_port_csv": COMBINED_ONE_PORT_CHKSTD_CSV, "two_port_csv": COMBINED_TWO_PORT_CHKSTD_CSV, "two_port_nr_csv": TWO_PORT_NR_CHKSTD_CSV, "power_csv": COMBINED_POWER_CHKSTD_CSV, "outlier_removal": True, "last_n": 5, "download_formats": ["Csv"], "conversion_options":{ "nodes": ['CsvFile', 'ExcelFile'], "extensions": [ 'csv', 'xlsx'], "mime_types": ['text/plain', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']} } self.options = {} for key, value in defaults.items(): self.options[key] = value for key, value in options.items(): self.options[key] = value self.conversion_defaults = {"base_name": None, "nodes": ['XmlFile', 'CsvFile', 'ExcelFile', 'OdsFile', 'MatFile', 'HtmlFile', 'JsonFile'], "extensions": ['xml', 'csv', 'xlsx', 'ods', 'mat', 'html', 'json'], "mime_types": ['application/xml', 'text/plain', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.oasis.opendocument.spreadsheet', 'application/x-matlab-data', 'text/html', 'application/json']} # html_options={} if self.options["conversion_options"] is None: self.conversion_options=self.conversion_defaults else: self.conversion_options=self.options["conversion_options"] HTMLReport.__init__(self, None, **self.options) self.plots = [] self.plot_ids = [] self.plot_titles = [] self.plot_captions = [] # set up dtypes for pandas one_port_dtype = ONE_PORT_DTYPE # this reads the NISTModels constant if COMBINE_S11_S22: one_port_dtype["arg"] = 'float' one_port_dtype["mag"] = 'float' else: one_port_dtype["argS11"] = 'float' one_port_dtype["magS11"] = 'float' one_port_dtype["argS22"] = 'float' one_port_dtype["magS22"] = 'float' # create a history dictionary. # print("{0} is {1}".format("self.options",self.options)) self.history_dict = {'1-port': pandas.read_csv(self.options["one_port_csv"], dtype=one_port_dtype), '2-port': pandas.read_csv(self.options["two_port_csv"]), '2-portNR': pandas.read_csv(self.options["two_port_nr_csv"]), 'power': pandas.read_csv(self.options["power_csv"])} if file_path is None: # plot the results file self.build_checkstandard_report() else: self.build_comparison_report(file_path) def build_checkstandard_report(self): """Builds the report for the options Device_Id""" self.raw_measurement=None self.calrep_measurement=None self.clear() self.plots = [] self.plot_ids = [] self.plot_captions = [] self.plot_titles = [] measurement_type = self.options["Device_Id"][-3] if re.match("1", measurement_type): self.options["Measurement_Type"] = "1-port" elif re.match("2", measurement_type): self.options["Measurement_Type"] = "2-port" elif re.match("p", measurement_type, re.IGNORECASE): self.options["Measurement_Type"] = "power" print(("{0} is {1}".format("measurement_type",measurement_type))) try: self.results_file = ResultFileModel(os.path.join(self.options["results_directory"], self.options["Device_Id"])) except: self.results_file=ResultFileModel(None) options = {"Device_Id": self.options["Device_Id"], "System_Id": None, "Measurement_Timestamp": None, "Connector_Type_Measurement": None, "Measurement_Date": None, "Measurement_Time": None, "outlier_removal": False} if re.search('2-port', self.options["Measurement_Type"], re.IGNORECASE): history_key = '2-port' options["column_names"] = ['Frequency', 'magS11', 'argS11', 'magS21', 'argS21', 'magS22', 'argS22'] elif re.search('1-port', self.options["Measurement_Type"], re.IGNORECASE): history_key = '1-port' if COMBINE_S11_S22: options["column_names"] = ['Frequency', 'magS11', 'argS11'] else: options["column_names"] = ['Frequency', 'magS11', 'argS11', 'magS22', 'argS22'] elif re.search('Dry Cal|Thermistor|power', self.options["Measurement_Type"], re.IGNORECASE): history_key = 'power' options["column_names"] = ['Frequency', 'magS11', 'argS11', 'Efficiency'] # print history[history_key][:5] # print history_key database = self.history_dict[history_key] self.device_history = database[database["Device_Id"] == self.options["Device_Id"]] if self.options["outlier_removal"]: self.outlier_removal() self.mean_frame = mean_from_history(self.device_history, **options) self.plots.append(plot_checkstandard_history(self.device_history)) self.plot_ids.append("completeHistory") self.plot_titles.append("The Complete History of {0}".format(self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Every measurement of {1} currently in the database.""".format(len(self.plots), self.options["Device_Id"])) self.plots.append(plot_checkstandard_history(self.device_history, min_num=len(self.get_measurement_dates()) - self.options[ "last_n"] - 1, max_num=len(self.get_measurement_dates()) - 1, extra_plots=[self.results_file, self.mean_frame], extra_plot_labels=["Historical Database", "Mean of New Database"], extra_plot_formats=["r--", "k^"])) self.plot_ids.append("partialHistory") self.plot_titles.append("""The last {0} measurements of {1} compared with the historical database and mean. """.format(self.options["last_n"], self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Last {1} measurements of {2} compared with historical database and mean""".format(len(self.plots), self.options["last_n"], self.options["Device_Id"])) self.add_toggle_support() summary_text = """ This device has been measured {0} times from {1} to {2}""".format(len(self.get_measurement_dates()), min(self.get_measurement_dates()), max(self.get_measurement_dates())) self.add_report_heading() self.append_to_body({"tag": "p", "text": summary_text}) download_options={"mime_types":self.conversion_options["mime_types"], "download_formats":self.conversion_options["nodes"], "download_extensions":self.conversion_options["extensions"], "clear_before": False, "download_files": [self.results_file, self.mean_frame, self.device_history], "download_files_input_format": ["AsciiDataTable", "DataFrame", "DataFrame"], "download_files_base_names": ["Historical_Database.txt", "Mean_Database.txt", "Device_History.txt"], "style": "display:none;border:1;"} self.add_download_table(**download_options) self.add_all_plots() def build_comparison_report(self, raw_file_path=None): """Builds the report for a raw file comparison, requires a raw_file_path to process""" self.clear() self.plots = [] self.plot_ids = [] self.plot_captions = [] self.plot_titles = [] self.raw_measurement_model = sparameter_power_type(raw_file_path) self.raw_measurement = globals()[self.raw_measurement_model](raw_file_path) # print("{0} is {1}".format("self.raw_measurement.column_names",self.raw_measurement.column_names)) table = self.raw_measurement self.options["Device_Id"] = table.metadata["Device_Id"] self.plots.append(self.raw_measurement.show()) self.plot_ids.append("rawMeasurement") self.plot_titles.append("Raw Measurement of {0}".format(self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Raw measurement of {1}. The measurement of check standard {1} in a calibrated mode.""".format(len(self.plots), self.options["Device_Id"])) self.calrep_measurement = calrep(self.raw_measurement) self.plots.append(plot_calrep(self.calrep_measurement)) self.plot_ids.append("clarepMeasurement") self.plot_titles.append("Plot of {0} with uncertainty".format(self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Measurement of {1}. The measurement of check standard {1} with nist total uncertainty.""".format(len(self.plots), self.options["Device_Id"])) self.plots.append(plot_calrep_uncertainty(self.calrep_measurement)) self.plot_ids.append("clarepUncert") self.plot_titles.append("Plot Uncertainty Components".format(self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Uncertainty Components. The uncertainty in measurement of check standard {1} .""".format(len(self.plots), self.options["Device_Id"])) try: self.results_file = ResultFileModel(os.path.join(self.options["results_directory"], self.calrep_measurement.metadata["Device_Id"])) except: self.results_file = None options = {"Device_Id": table.metadata["Device_Id"], "System_Id": table.metadata["System_Id"], "Measurement_Timestamp": None, "Connector_Type_Measurement": table.metadata["Connector_Type_Measurement"], "Measurement_Date": None, "Measurement_Time": None, "outlier_removal": False} if re.search('2-port', table.metadata["Measurement_Type"], re.IGNORECASE) and not re.search('2-portNR', table.metadata["Measurement_Type"], re.IGNORECASE): history_key = '2-port' options["column_names"] = ['Frequency', 'magS11', 'argS11', 'magS21', 'argS21', 'magS22', 'argS22'] elif re.search('2-portNR', table.metadata["Measurement_Type"], re.IGNORECASE): history_key = '2-portNR' options["column_names"] = ['Frequency', 'magS11', 'argS11', 'magS12', 'argS12', 'magS21', 'argS21', 'magS22', 'argS22'] elif re.search('1-port', table.metadata["Measurement_Type"], re.IGNORECASE): history_key = '1-port' if COMBINE_S11_S22: options["column_names"] = ['Frequency', 'magS11', 'argS11'] else: options["column_names"] = ['Frequency', 'magS11', 'argS11', 'magS22', 'argS22'] elif re.search('Dry Cal|Thermistor|power', table.metadata["Measurement_Type"], re.IGNORECASE): history_key = 'power' options["column_names"] = ['Frequency', 'magS11', 'argS11', 'Efficiency'] # print history[history_key][:5] # print history_key database = self.history_dict[history_key] self.device_history = database[database["Device_Id"] == self.options["Device_Id"]] if self.options["outlier_removal"]: self.outlier_removal() self.mean_frame = mean_from_history(self.device_history.copy(), **options) # print mean_frame self.difference_frame = raw_difference_frame(table, self.mean_frame) # print("{0} is {1}".format("self.raw_measurement.column_names",self.raw_measurement.column_names)) # print difference_frame self.plots.append(raw_comparison_plot_with_residuals(table, self.mean_frame, self.difference_frame)) self.plot_ids.append("rawSummary") self.plot_titles.append("Summary of Measurement and Mean of Complete Database with Resisduals") self.plot_captions.append("""Figure {0}. Summary of Measurement and Mean with Resisduals. Data for all measurements are being used""".format(len(self.plots))) # stop_time=datetime.datetime.now() # diff=stop_time-start_time self.plots.append(plot_calrep_results_comparison(self.calrep_measurement, self.results_file, display_legend=True)) self.plot_ids.append("compareWithUncertainty") self.plot_titles.append("Measurement with Uncertainties compared with Historical Database") self.plot_captions.append("""Figure {0}. Measurement with Uncertainties compared with Historical Database. This is the current selection criteria""".format(len(self.plots))) self.plots.append(plot_calrep_results_difference_comparison(self.calrep_measurement, self.results_file, display_legend=True)) self.plot_ids.append("compareWithUncertaintyDifference") self.plot_titles.append("The Difference of Measurement with Uncertainties compared with Historical Database") self.plot_captions.append("""Figure {0}. The Difference of Measurement with Uncertainties compared with Historical Database. This is the current selection criteria.""".format(len(self.plots))) column_names = return_calrep_value_column_names(self.calrep_measurement) error_column_names = return_calrep_error_column_names(column_names) self.standard_error = standard_error_data_table(self.calrep_measurement, self.results_file, table_1_uncertainty_column_names=error_column_names, value_column_names=column_names, expansion_factor=1) number_columns_pass = list(self.standard_error.get_conformation_dictionary().values()).count(True) number_columns = len(list(self.standard_error.get_conformation_dictionary().values())) good = int(round(float(number_columns_pass - 1) / float(number_columns - 1))) pass_fail = "" if good: pass_fail = "PASSES" else: pass_fail = "FAILS" self.plots.append(self.standard_error.show()) self.plot_ids.append("standardErrror") self.plot_titles.append( "The Standard Error of Measurement with Uncertainties compared with Historical Database") self.plot_captions.append("""Figure {0}. The Standard Error of Measurement with Uncertainties compared with Historical Database. This is the current selection criteria.""".format(len(self.plots))) self.plots.append(plot_checkstandard_history(self.device_history)) self.plot_ids.append("completeHistory") self.plot_titles.append("The Complete History of {0}".format(self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Every measurement of {1} currently in the database.""".format(len(self.plots), self.options["Device_Id"])) self.plots.append(plot_checkstandard_history(self.device_history, min_num=len(self.get_measurement_dates()) - self.options[ "last_n"] - 1, max_num=len(self.get_measurement_dates()) - 1, extra_plots=[self.results_file, self.mean_frame], extra_plot_labels=["Historical Database", "Mean of New Database"], extra_plot_formats=["r--", "k^"])) self.plot_ids.append("partialHistory") self.plot_titles.append("""The last {0} measurements of {1} compared with the historical database and mean. """.format(self.options["last_n"], self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Last {1} measurements of {2} compared with historical database and mean""".format(len(self.plots), self.options["last_n"], self.options["Device_Id"])) self.add_toggle_support() summary_text = """This is a summary of the measurement of {0} made on {1} by {2}. This measurement {3} the checkstandard process. This device has been measured {4} times from {5} to {6}""".format(self.options["Device_Id"], self.raw_measurement.metadata[ "Measurement_Date"], self.raw_measurement.metadata["Operator"], pass_fail, len(self.get_measurement_dates()), min(self.get_measurement_dates()), max(self.get_measurement_dates())) self.add_report_heading() self.append_to_body({"tag": "p", "text": summary_text}) self.add_download_table(download_extensions=self.conversion_options["extensions"], download_formats=self.conversion_options["nodes"], mime_types=self.conversion_options["mime_types"]) self.add_table_border_style() self.add_metadata_section() self.add_all_plots() def get_measurement_dates(self): """Returns measurement dates from self.device_history""" dates = sorted(self.device_history["Measurement_Timestamp"].unique()) self.measurement_dates = dates[:] return dates def outlier_removal(self): """Removes outliers frome self.device_history""" mean_s11 = np.mean(self.device_history["magS11"]) std_s11 = np.std(self.device_history["magS11"]) self.device_history = self.device_history[self.device_history["magS11"] < (mean_s11 + 3 * std_s11)] self.device_history = self.device_history[self.device_history["magS11"] > (mean_s11 - 3 * std_s11)] def add_all_plots(self, **options): """Adds all plots in the attribute self.plots""" defaults = {"clear_before": False, "style": "display:none", "figure_width": 14} add_options = {} for key, value in defaults.items(): add_options[key] = value for key, value in options.items(): add_optionss[key] = value if add_options["clear_before"]: self.clear() for index, plot in enumerate(self.plots): id_text = self.plot_ids[index] self.append_to_body({"tag": "hr"}) self.append_to_body({"tag": "h2", "text": self.plot_titles[index]}) self.add_toggle(id_text) plot.set_figwidth(add_options["figure_width"]) self.embedd_image_figure(plot, figure_id="{0}".format(id_text), style=add_options["style"], caption=self.plot_captions[index]) self.append_to_body({"tag": "hr"}) def add_report_heading(self, heading_text=None, **options): """Adds a heading to the report, clears the report by default""" defaults = {"clear_before": False} add_options = {} for key, value in defaults.items(): add_options[key] = value for key, value in options.items(): add_options[key] = value if add_options["clear_before"]: self.clear() if heading_text is None: heading_text = "Check Standard Report for {0}".format(self.options["Device_Id"]) self.append_to_body({"tag": "h1", "text": heading_text}) def add_toggle_support(self): """Adds a toggle style and script to the report""" self.add_toggle_script() self.add_toggle_style() def add_download_table(self, download_formats=["CsvFile", "ExcelFile"], download_extensions=["csv", "xlsx"], mime_types=["text/plain", 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], **options): """Adds a table of downloadable files""" defaults = {"clear_before": False, "download_files": [self.raw_measurement, self.calrep_measurement, self.results_file, self.mean_frame, self.device_history], "download_files_input_format": ["AsciiDataTable", "AsciiDataTable", "AsciiDataTable", "DataFrame", "DataFrame"], "download_files_base_names": ["Raw_Measurement.txt", "Measurement_NIST_Uncertainties.txt", "Historical_Database.txt", "Mean_Database.txt", "Device_History.txt"], "style": "display:none;border:1;"} add_options = {} for key, value in defaults.items(): add_options[key] = value for key, value in options.items(): add_options[key] = value if add_options["clear_before"]: self.clear() self.append_to_body({"tag": "h2", "text": "Downloads"}) self.add_toggle("downloads") table_graph = TableGraph() # convert all data to AsciiDataTable format download_table = "<table id='downloads' style='{0}'>".format(add_options["style"]) for index, download in enumerate(add_options["download_files"][:]): if add_options["download_files_input_format"][index] not in ["AsciiDataTable"]: table_graph.set_state(add_options["download_files_input_format"][index], download) table_graph.move_to_node("AsciiDataTable") download = table_graph.data.copy() # now we cycle throught the download formats, for each file we load the graph and then create the download links ascii_download = String_to_DownloadLink(string=str(download), mime_type="text/plain", suggested_name=add_options["download_files_base_names"][index], text=add_options["download_files_base_names"][index]) #print(("{0} is {1}".format("index", index))) table_graph.set_state("AsciiDataTable", download) download_links = TableGraph_to_Links(table_graph, base_name=add_options["download_files_base_names"][index], nodes=download_formats, extensions=download_extensions, mime_types=mime_types) download_table = download_table + "<tr><td>{0}</td><td>{1}</td></tr>".format(ascii_download, download_links) download_table = download_table + "</table>" self.append_to_body(download_table) self.append_to_body({"tag": "hr"}) def add_metadata_section(self, style="display:none;border: 1px solid black;"): """Adds a metadata section if self.raw_measurement exits""" try: self.append_to_body({"tag": "h2", "text": "Measurement Metadata"}) self.add_toggle("metadata") self.append_to_body({"tag": "hr"}) meta_table = "<table id='metadata' style='{0}'>".format(style) for key, value in self.raw_measurement.metadata.items(): meta_table = meta_table + "<tr><td>{0}</td><td>{1}</td></tr>".format(key, value) meta_table = meta_table + "</table>" self.append_to_body(meta_table) except: pass def add_table_border_style(self): """Adds a css style tag to the head of the sheet to display all borders""" self.append_to_head({"tag": "style", "text": """table, th, td { border: 1px solid black;}"""})
Ancestors (in MRO)
- CheckStandardReport
- HTMLReport
- Code.DataHandlers.HTMLModels.HTMLBase
- __builtin__.object
Instance variables
var conversion_defaults
var history_dict
var options
var plot_ids
var plot_titles
var plots
Methods
def __init__(
self, file_path=None, **options)
Inheritance:
HTMLReport
.__init__
Initializes the CheckStandardReport Class
def __init__(self, file_path=None, **options): """Initializes the CheckStandardReport Class""" defaults = {"Device_Id": "CTN112", "results_directory": r'C:\Share\resfiles', "one_port_csv": COMBINED_ONE_PORT_CHKSTD_CSV, "two_port_csv": COMBINED_TWO_PORT_CHKSTD_CSV, "two_port_nr_csv": TWO_PORT_NR_CHKSTD_CSV, "power_csv": COMBINED_POWER_CHKSTD_CSV, "outlier_removal": True, "last_n": 5, "download_formats": ["Csv"], "conversion_options":{ "nodes": ['CsvFile', 'ExcelFile'], "extensions": [ 'csv', 'xlsx'], "mime_types": ['text/plain', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']} } self.options = {} for key, value in defaults.items(): self.options[key] = value for key, value in options.items(): self.options[key] = value self.conversion_defaults = {"base_name": None, "nodes": ['XmlFile', 'CsvFile', 'ExcelFile', 'OdsFile', 'MatFile', 'HtmlFile', 'JsonFile'], "extensions": ['xml', 'csv', 'xlsx', 'ods', 'mat', 'html', 'json'], "mime_types": ['application/xml', 'text/plain', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.oasis.opendocument.spreadsheet', 'application/x-matlab-data', 'text/html', 'application/json']} # html_options={} if self.options["conversion_options"] is None: self.conversion_options=self.conversion_defaults else: self.conversion_options=self.options["conversion_options"] HTMLReport.__init__(self, None, **self.options) self.plots = [] self.plot_ids = [] self.plot_titles = [] self.plot_captions = [] # set up dtypes for pandas one_port_dtype = ONE_PORT_DTYPE # this reads the NISTModels constant if COMBINE_S11_S22: one_port_dtype["arg"] = 'float' one_port_dtype["mag"] = 'float' else: one_port_dtype["argS11"] = 'float' one_port_dtype["magS11"] = 'float' one_port_dtype["argS22"] = 'float' one_port_dtype["magS22"] = 'float' # create a history dictionary. # print("{0} is {1}".format("self.options",self.options)) self.history_dict = {'1-port': pandas.read_csv(self.options["one_port_csv"], dtype=one_port_dtype), '2-port': pandas.read_csv(self.options["two_port_csv"]), '2-portNR': pandas.read_csv(self.options["two_port_nr_csv"]), 'power': pandas.read_csv(self.options["power_csv"])} if file_path is None: # plot the results file self.build_checkstandard_report() else: self.build_comparison_report(file_path)
def add_all_plots(
self, **options)
Adds all plots in the attribute self.plots
def add_all_plots(self, **options): """Adds all plots in the attribute self.plots""" defaults = {"clear_before": False, "style": "display:none", "figure_width": 14} add_options = {} for key, value in defaults.items(): add_options[key] = value for key, value in options.items(): add_optionss[key] = value if add_options["clear_before"]: self.clear() for index, plot in enumerate(self.plots): id_text = self.plot_ids[index] self.append_to_body({"tag": "hr"}) self.append_to_body({"tag": "h2", "text": self.plot_titles[index]}) self.add_toggle(id_text) plot.set_figwidth(add_options["figure_width"]) self.embedd_image_figure(plot, figure_id="{0}".format(id_text), style=add_options["style"], caption=self.plot_captions[index]) self.append_to_body({"tag": "hr"})
def add_body(
self)
Inheritance:
HTMLReport
.add_body
Adds a body tag to the model if it does not exist
def add_body(self): """Adds a body tag to the model if it does not exist""" body=make_html_element(tag="body",text="") tags=[x.tag.lower() for x in self.root.getchildren()] if not "body" in tags: self.root.append(body) else: print("body already exists, tag was not added ") pass self.body=self.root.body
def add_download_link(
self, content_string, text='Download File', suggested_name='test.txt', mime_type='text/plain')
Inheritance:
HTMLReport
.add_download_link
Adds a download link to the report
def add_download_link(self, content_string, text="Download File", suggested_name="test.txt", mime_type="text/plain"): """Adds a download link to the report""" self.append_to_body(String_to_DownloadLink(content_string, text=text, suggested_name=suggested_name, mime_type=mime_type))
def add_download_table(
self, download_formats=['CsvFile', 'ExcelFile'], download_extensions=['csv', 'xlsx'], mime_types=['text/plain', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], **options)
Adds a table of downloadable files
def add_download_table(self, download_formats=["CsvFile", "ExcelFile"], download_extensions=["csv", "xlsx"], mime_types=["text/plain", 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], **options): """Adds a table of downloadable files""" defaults = {"clear_before": False, "download_files": [self.raw_measurement, self.calrep_measurement, self.results_file, self.mean_frame, self.device_history], "download_files_input_format": ["AsciiDataTable", "AsciiDataTable", "AsciiDataTable", "DataFrame", "DataFrame"], "download_files_base_names": ["Raw_Measurement.txt", "Measurement_NIST_Uncertainties.txt", "Historical_Database.txt", "Mean_Database.txt", "Device_History.txt"], "style": "display:none;border:1;"} add_options = {} for key, value in defaults.items(): add_options[key] = value for key, value in options.items(): add_options[key] = value if add_options["clear_before"]: self.clear() self.append_to_body({"tag": "h2", "text": "Downloads"}) self.add_toggle("downloads") table_graph = TableGraph() # convert all data to AsciiDataTable format download_table = "<table id='downloads' style='{0}'>".format(add_options["style"]) for index, download in enumerate(add_options["download_files"][:]): if add_options["download_files_input_format"][index] not in ["AsciiDataTable"]: table_graph.set_state(add_options["download_files_input_format"][index], download) table_graph.move_to_node("AsciiDataTable") download = table_graph.data.copy() # now we cycle throught the download formats, for each file we load the graph and then create the download links ascii_download = String_to_DownloadLink(string=str(download), mime_type="text/plain", suggested_name=add_options["download_files_base_names"][index], text=add_options["download_files_base_names"][index]) #print(("{0} is {1}".format("index", index))) table_graph.set_state("AsciiDataTable", download) download_links = TableGraph_to_Links(table_graph, base_name=add_options["download_files_base_names"][index], nodes=download_formats, extensions=download_extensions, mime_types=mime_types) download_table = download_table + "<tr><td>{0}</td><td>{1}</td></tr>".format(ascii_download, download_links) download_table = download_table + "</table>" self.append_to_body(download_table) self.append_to_body({"tag": "hr"})
def add_head(
self)
Inheritance:
HTMLReport
.add_head
Adds a head tag to the model if it does not exist
def add_head(self): """Adds a head tag to the model if it does not exist""" head=make_html_element(tag="head",text="") if len(self.root.getchildren())==0: self.root.append(head) elif not re.match("head",self.root.getchildren()[0].tag,re.IGNORECASE) and len(self.root.getchildren())>0: self.root.insert(0,head) else: print("head already exists, tag was not added ") self.head=self.root.head
def add_metadata_section(
self, style='display:none;border: 1px solid black;')
Adds a metadata section if self.raw_measurement exits
def add_metadata_section(self, style="display:none;border: 1px solid black;"): """Adds a metadata section if self.raw_measurement exits""" try: self.append_to_body({"tag": "h2", "text": "Measurement Metadata"}) self.add_toggle("metadata") self.append_to_body({"tag": "hr"}) meta_table = "<table id='metadata' style='{0}'>".format(style) for key, value in self.raw_measurement.metadata.items(): meta_table = meta_table + "<tr><td>{0}</td><td>{1}</td></tr>".format(key, value) meta_table = meta_table + "</table>" self.append_to_body(meta_table) except: pass
def add_report_heading(
self, heading_text=None, **options)
Adds a heading to the report, clears the report by default
def add_report_heading(self, heading_text=None, **options): """Adds a heading to the report, clears the report by default""" defaults = {"clear_before": False} add_options = {} for key, value in defaults.items(): add_options[key] = value for key, value in options.items(): add_options[key] = value if add_options["clear_before"]: self.clear() if heading_text is None: heading_text = "Check Standard Report for {0}".format(self.options["Device_Id"]) self.append_to_body({"tag": "h1", "text": heading_text})
def add_table_border_style(
self)
Adds a css style tag to the head of the sheet to display all borders
def add_table_border_style(self): """Adds a css style tag to the head of the sheet to display all borders""" self.append_to_head({"tag": "style", "text": """table, th, td { border: 1px solid black;}"""})
def add_toggle(
self, tag_id=None)
Inheritance:
HTMLReport
.add_toggle
Adds a toggle button that toggles the element with id tag_id. This can be used many times
def add_toggle(self, tag_id=None): """Adds a toggle button that toggles the element with id tag_id. This can be used many times """ toggle = '<input type="button" class="toggleButton" value="+" onclick="toggleId(\'{0}\',this)">'.format(tag_id) self.append_to_body(toggle)
def add_toggle_script(
self, script='<script type="text/javascript">\n function toggleId(id,$link){\n $node = document.getElementById(id);\n if (!$node)\n return;\n if (!$node.style.display || $node.style.display == \'none\') {\n $node.style.display = \'block\';\n $link.value = \'-\';\n } else {\n $node.style.display = \'none\';\n $link.value = \'+\';\n }\n }\n </script>')
Inheritance:
HTMLReport
.add_toggle_script
Adds a javascript template toggle script to the body of the HTML
def add_toggle_script(self, script=DEFAULT_TOGGLE_SCRIPT): """Adds a javascript template toggle script to the body of the HTML""" self.append_to_body(script)
def add_toggle_style(
self, style='<style>\n .toggleButton {\n background-color: white;\n border: 2px solid black;\n border-radius: 8px;\n color:red;\n\t }\n .toggleButton:hover {\n box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);\n\t}\n </stlye>')
Inheritance:
HTMLReport
.add_toggle_style
Adds a css to format the javascript template, should be done once
def add_toggle_style(self, style=DEFAULT_TOGGLE_STYLE): """Adds a css to format the javascript template, should be done once""" self.append_to_head(style)
def add_toggle_support(
self)
Adds a toggle style and script to the report
def add_toggle_support(self): """Adds a toggle style and script to the report""" self.add_toggle_script() self.add_toggle_style()
def append_to_body(
self, element)
Inheritance:
HTMLReport
.append_to_body
Appends the element to the body of the model, if it is a string it parses first, if it is a dictionary it assumes it has the form {"tag":tag_name,"text":text_text, "attribute_dictionary":{"attribute_name":"attribute_value"}, and if it is a lxml.html.HtmlElement it appends it
def append_to_body(self,element): """Appends the element to the body of the model, if it is a string it parses first, if it is a dictionary it assumes it has the form {"tag":tag_name,"text":text_text, "attribute_dictionary":{"attribute_name":"attribute_value"}, and if it is a lxml.html.HtmlElement it appends it""" try: tags = [x.tag.lower() for x in self.root.getchildren()] if not "body" in tags: body = make_html_element(tag="body", text="") print("Body tag was not present adding it") self.root.append(body) if isinstance(element, StringType): new_element=lxml.html.fragment_fromstring(element) elif isinstance(element, DictionaryType): new_element=make_html_element(**element) elif isinstance(element,lxml.html.HtmlElement): new_element=element self.root.body.append(new_element) except: print(("Could not add {0} to body".format(element)))
def append_to_head(
self, element)
Inheritance:
HTMLReport
.append_to_head
Appends the element to the head of the model, if it is a string it parses first, if it is a dictionary it assumes it has the form {"tag":tag_name,"text":text_text, "attribute_dictionary":{"attribute_name":"attribute_value"}, and if it is a lxml.html.HtmlElement it appends it
def append_to_head(self,element): """Appends the element to the head of the model, if it is a string it parses first, if it is a dictionary it assumes it has the form {"tag":tag_name,"text":text_text, "attribute_dictionary":{"attribute_name":"attribute_value"}, and if it is a lxml.html.HtmlElement it appends it""" try: tags = [x.tag.lower() for x in self.root.getchildren()] if not "head" in tags: head = make_html_element(tag="head", text="") print("Head tag was not present adding it") self.root.insert(0,head) if isinstance(element, StringType): new_element=lxml.html.fragment_fromstring(element) elif isinstance(element, DictionaryType): new_element=make_html_element(**element) elif isinstance(element,lxml.html.HtmlElement): new_element=element self.root.head.append(new_element) except: print(("Could not add {0} to head".format(element)))
def build_checkstandard_report(
self)
Builds the report for the options Device_Id
def build_checkstandard_report(self): """Builds the report for the options Device_Id""" self.raw_measurement=None self.calrep_measurement=None self.clear() self.plots = [] self.plot_ids = [] self.plot_captions = [] self.plot_titles = [] measurement_type = self.options["Device_Id"][-3] if re.match("1", measurement_type): self.options["Measurement_Type"] = "1-port" elif re.match("2", measurement_type): self.options["Measurement_Type"] = "2-port" elif re.match("p", measurement_type, re.IGNORECASE): self.options["Measurement_Type"] = "power" print(("{0} is {1}".format("measurement_type",measurement_type))) try: self.results_file = ResultFileModel(os.path.join(self.options["results_directory"], self.options["Device_Id"])) except: self.results_file=ResultFileModel(None) options = {"Device_Id": self.options["Device_Id"], "System_Id": None, "Measurement_Timestamp": None, "Connector_Type_Measurement": None, "Measurement_Date": None, "Measurement_Time": None, "outlier_removal": False} if re.search('2-port', self.options["Measurement_Type"], re.IGNORECASE): history_key = '2-port' options["column_names"] = ['Frequency', 'magS11', 'argS11', 'magS21', 'argS21', 'magS22', 'argS22'] elif re.search('1-port', self.options["Measurement_Type"], re.IGNORECASE): history_key = '1-port' if COMBINE_S11_S22: options["column_names"] = ['Frequency', 'magS11', 'argS11'] else: options["column_names"] = ['Frequency', 'magS11', 'argS11', 'magS22', 'argS22'] elif re.search('Dry Cal|Thermistor|power', self.options["Measurement_Type"], re.IGNORECASE): history_key = 'power' options["column_names"] = ['Frequency', 'magS11', 'argS11', 'Efficiency'] # print history[history_key][:5] # print history_key database = self.history_dict[history_key] self.device_history = database[database["Device_Id"] == self.options["Device_Id"]] if self.options["outlier_removal"]: self.outlier_removal() self.mean_frame = mean_from_history(self.device_history, **options) self.plots.append(plot_checkstandard_history(self.device_history)) self.plot_ids.append("completeHistory") self.plot_titles.append("The Complete History of {0}".format(self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Every measurement of {1} currently in the database.""".format(len(self.plots), self.options["Device_Id"])) self.plots.append(plot_checkstandard_history(self.device_history, min_num=len(self.get_measurement_dates()) - self.options[ "last_n"] - 1, max_num=len(self.get_measurement_dates()) - 1, extra_plots=[self.results_file, self.mean_frame], extra_plot_labels=["Historical Database", "Mean of New Database"], extra_plot_formats=["r--", "k^"])) self.plot_ids.append("partialHistory") self.plot_titles.append("""The last {0} measurements of {1} compared with the historical database and mean. """.format(self.options["last_n"], self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Last {1} measurements of {2} compared with historical database and mean""".format(len(self.plots), self.options["last_n"], self.options["Device_Id"])) self.add_toggle_support() summary_text = """ This device has been measured {0} times from {1} to {2}""".format(len(self.get_measurement_dates()), min(self.get_measurement_dates()), max(self.get_measurement_dates())) self.add_report_heading() self.append_to_body({"tag": "p", "text": summary_text}) download_options={"mime_types":self.conversion_options["mime_types"], "download_formats":self.conversion_options["nodes"], "download_extensions":self.conversion_options["extensions"], "clear_before": False, "download_files": [self.results_file, self.mean_frame, self.device_history], "download_files_input_format": ["AsciiDataTable", "DataFrame", "DataFrame"], "download_files_base_names": ["Historical_Database.txt", "Mean_Database.txt", "Device_History.txt"], "style": "display:none;border:1;"} self.add_download_table(**download_options) self.add_all_plots()
def build_comparison_report(
self, raw_file_path=None)
Builds the report for a raw file comparison, requires a raw_file_path to process
def build_comparison_report(self, raw_file_path=None): """Builds the report for a raw file comparison, requires a raw_file_path to process""" self.clear() self.plots = [] self.plot_ids = [] self.plot_captions = [] self.plot_titles = [] self.raw_measurement_model = sparameter_power_type(raw_file_path) self.raw_measurement = globals()[self.raw_measurement_model](raw_file_path) # print("{0} is {1}".format("self.raw_measurement.column_names",self.raw_measurement.column_names)) table = self.raw_measurement self.options["Device_Id"] = table.metadata["Device_Id"] self.plots.append(self.raw_measurement.show()) self.plot_ids.append("rawMeasurement") self.plot_titles.append("Raw Measurement of {0}".format(self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Raw measurement of {1}. The measurement of check standard {1} in a calibrated mode.""".format(len(self.plots), self.options["Device_Id"])) self.calrep_measurement = calrep(self.raw_measurement) self.plots.append(plot_calrep(self.calrep_measurement)) self.plot_ids.append("clarepMeasurement") self.plot_titles.append("Plot of {0} with uncertainty".format(self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Measurement of {1}. The measurement of check standard {1} with nist total uncertainty.""".format(len(self.plots), self.options["Device_Id"])) self.plots.append(plot_calrep_uncertainty(self.calrep_measurement)) self.plot_ids.append("clarepUncert") self.plot_titles.append("Plot Uncertainty Components".format(self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Uncertainty Components. The uncertainty in measurement of check standard {1} .""".format(len(self.plots), self.options["Device_Id"])) try: self.results_file = ResultFileModel(os.path.join(self.options["results_directory"], self.calrep_measurement.metadata["Device_Id"])) except: self.results_file = None options = {"Device_Id": table.metadata["Device_Id"], "System_Id": table.metadata["System_Id"], "Measurement_Timestamp": None, "Connector_Type_Measurement": table.metadata["Connector_Type_Measurement"], "Measurement_Date": None, "Measurement_Time": None, "outlier_removal": False} if re.search('2-port', table.metadata["Measurement_Type"], re.IGNORECASE) and not re.search('2-portNR', table.metadata["Measurement_Type"], re.IGNORECASE): history_key = '2-port' options["column_names"] = ['Frequency', 'magS11', 'argS11', 'magS21', 'argS21', 'magS22', 'argS22'] elif re.search('2-portNR', table.metadata["Measurement_Type"], re.IGNORECASE): history_key = '2-portNR' options["column_names"] = ['Frequency', 'magS11', 'argS11', 'magS12', 'argS12', 'magS21', 'argS21', 'magS22', 'argS22'] elif re.search('1-port', table.metadata["Measurement_Type"], re.IGNORECASE): history_key = '1-port' if COMBINE_S11_S22: options["column_names"] = ['Frequency', 'magS11', 'argS11'] else: options["column_names"] = ['Frequency', 'magS11', 'argS11', 'magS22', 'argS22'] elif re.search('Dry Cal|Thermistor|power', table.metadata["Measurement_Type"], re.IGNORECASE): history_key = 'power' options["column_names"] = ['Frequency', 'magS11', 'argS11', 'Efficiency'] # print history[history_key][:5] # print history_key database = self.history_dict[history_key] self.device_history = database[database["Device_Id"] == self.options["Device_Id"]] if self.options["outlier_removal"]: self.outlier_removal() self.mean_frame = mean_from_history(self.device_history.copy(), **options) # print mean_frame self.difference_frame = raw_difference_frame(table, self.mean_frame) # print("{0} is {1}".format("self.raw_measurement.column_names",self.raw_measurement.column_names)) # print difference_frame self.plots.append(raw_comparison_plot_with_residuals(table, self.mean_frame, self.difference_frame)) self.plot_ids.append("rawSummary") self.plot_titles.append("Summary of Measurement and Mean of Complete Database with Resisduals") self.plot_captions.append("""Figure {0}. Summary of Measurement and Mean with Resisduals. Data for all measurements are being used""".format(len(self.plots))) # stop_time=datetime.datetime.now() # diff=stop_time-start_time self.plots.append(plot_calrep_results_comparison(self.calrep_measurement, self.results_file, display_legend=True)) self.plot_ids.append("compareWithUncertainty") self.plot_titles.append("Measurement with Uncertainties compared with Historical Database") self.plot_captions.append("""Figure {0}. Measurement with Uncertainties compared with Historical Database. This is the current selection criteria""".format(len(self.plots))) self.plots.append(plot_calrep_results_difference_comparison(self.calrep_measurement, self.results_file, display_legend=True)) self.plot_ids.append("compareWithUncertaintyDifference") self.plot_titles.append("The Difference of Measurement with Uncertainties compared with Historical Database") self.plot_captions.append("""Figure {0}. The Difference of Measurement with Uncertainties compared with Historical Database. This is the current selection criteria.""".format(len(self.plots))) column_names = return_calrep_value_column_names(self.calrep_measurement) error_column_names = return_calrep_error_column_names(column_names) self.standard_error = standard_error_data_table(self.calrep_measurement, self.results_file, table_1_uncertainty_column_names=error_column_names, value_column_names=column_names, expansion_factor=1) number_columns_pass = list(self.standard_error.get_conformation_dictionary().values()).count(True) number_columns = len(list(self.standard_error.get_conformation_dictionary().values())) good = int(round(float(number_columns_pass - 1) / float(number_columns - 1))) pass_fail = "" if good: pass_fail = "PASSES" else: pass_fail = "FAILS" self.plots.append(self.standard_error.show()) self.plot_ids.append("standardErrror") self.plot_titles.append( "The Standard Error of Measurement with Uncertainties compared with Historical Database") self.plot_captions.append("""Figure {0}. The Standard Error of Measurement with Uncertainties compared with Historical Database. This is the current selection criteria.""".format(len(self.plots))) self.plots.append(plot_checkstandard_history(self.device_history)) self.plot_ids.append("completeHistory") self.plot_titles.append("The Complete History of {0}".format(self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Every measurement of {1} currently in the database.""".format(len(self.plots), self.options["Device_Id"])) self.plots.append(plot_checkstandard_history(self.device_history, min_num=len(self.get_measurement_dates()) - self.options[ "last_n"] - 1, max_num=len(self.get_measurement_dates()) - 1, extra_plots=[self.results_file, self.mean_frame], extra_plot_labels=["Historical Database", "Mean of New Database"], extra_plot_formats=["r--", "k^"])) self.plot_ids.append("partialHistory") self.plot_titles.append("""The last {0} measurements of {1} compared with the historical database and mean. """.format(self.options["last_n"], self.options["Device_Id"])) self.plot_captions.append("""Figure {0}. Last {1} measurements of {2} compared with historical database and mean""".format(len(self.plots), self.options["last_n"], self.options["Device_Id"])) self.add_toggle_support() summary_text = """This is a summary of the measurement of {0} made on {1} by {2}. This measurement {3} the checkstandard process. This device has been measured {4} times from {5} to {6}""".format(self.options["Device_Id"], self.raw_measurement.metadata[ "Measurement_Date"], self.raw_measurement.metadata["Operator"], pass_fail, len(self.get_measurement_dates()), min(self.get_measurement_dates()), max(self.get_measurement_dates())) self.add_report_heading() self.append_to_body({"tag": "p", "text": summary_text}) self.add_download_table(download_extensions=self.conversion_options["extensions"], download_formats=self.conversion_options["nodes"], mime_types=self.conversion_options["mime_types"]) self.add_table_border_style() self.add_metadata_section() self.add_all_plots()
def clear(
self)
Inheritance:
HTMLReport
.clear
Clears all content in the HTML
def clear(self): """Clears all content in the HTML""" element_list = self.root.getchildren() for child in element_list: self.root.remove(child)
def embedd_image(
self, image, image_mode='MatplotlibFigure', **options)
Inheritance:
HTMLReport
.embedd_image
Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values
def embedd_image(self, image, image_mode="MatplotlibFigure", **options): """Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values""" # might change this to self.ImageGraph and use it elsewhere image_graph = ImageGraph() image_graph.set_state(image_mode, image) image_graph.move_to_node("EmbeddedHtml") self.append_to_body(image_graph.data)
def embedd_image_figure(
self, image, image_mode='MatplotlibFigure', figure_id='image', caption='', style='', **options)
Inheritance:
HTMLReport
.embedd_image_figure
Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values. The image is in a
def embedd_image_figure(self, image, image_mode="MatplotlibFigure", figure_id="image", caption="", style="", **options): """Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values. The image is in a <figure id=figure_id> tag""" # might change this to self.ImageGraph and use it elsewhere image_graph = ImageGraph() image_graph.set_state(image_mode, image) image_graph.move_to_node("EmbeddedHtml") self.append_to_body("<figure id='{0}' style='{3}'>{1}<figcaption>{2}</figcaption></figure>".format(figure_id, image_graph.data, caption, style))
def get_measurement_dates(
self)
Returns measurement dates from self.device_history
def get_measurement_dates(self): """Returns measurement dates from self.device_history""" dates = sorted(self.device_history["Measurement_Timestamp"].unique()) self.measurement_dates = dates[:] return dates
def outlier_removal(
self)
Removes outliers frome self.device_history
def outlier_removal(self): """Removes outliers frome self.device_history""" mean_s11 = np.mean(self.device_history["magS11"]) std_s11 = np.std(self.device_history["magS11"]) self.device_history = self.device_history[self.device_history["magS11"] < (mean_s11 + 3 * std_s11)] self.device_history = self.device_history[self.device_history["magS11"] > (mean_s11 - 3 * std_s11)]
def save(
self, file_path=None, **temp_options)
Inheritance:
HTMLReport
.save
Saves the html file, provide file path to save as, or temp_options
def save(self,file_path=None,**temp_options): """Saves the html file, provide file path to save as, or temp_options""" original_options=self.options.copy() for key,value in temp_options.items(): self.options[key]=value if file_path is None: file_path=self.path out_file=open(file_path,"w") out_file.write(str(self)) out_file.close() self.options=original_options return file_path
def show(
self)
Inheritance:
HTMLReport
.show
Saves html to a temp file and shows it in a browser
def show(self): """Saves html to a temp file and shows it in a browser""" lxml.html.open_in_browser(self.document)
def to_HTML(
self)
Inheritance:
HTMLReport
.to_HTML
Convenience function that echos the content updates the attribute self.text
def to_HTML(self): """Convenience function that echos the content updates the attribute self.text""" self.text=str(self) return str(self.text)
def to_pdf(
self, file_path=None, **options)
Inheritance:
HTMLReport
.to_pdf
Converts the file to a pdf and saves it at file_path. If file_path is None, it will auto name the resulting file to self.path with pdf as the extension
def to_pdf(self,file_path=None,**options): """Converts the file to a pdf and saves it at file_path. If file_path is None, it will auto name the resulting file to self.path with pdf as the extension""" #todo: add toc and other options in wkhtmltopdf if file_path is None: file_path=change_extension(self.path,"pdf") config = pdfkit.configuration(wkhtmltopdf=WKHTML_PATH) pdfkit.from_string(str(self),file_path,configuration=config) return file_path
class HTMLReport
class HTMLReport(HTMLBase): def add_toggle_script(self, script=DEFAULT_TOGGLE_SCRIPT): """Adds a javascript template toggle script to the body of the HTML""" self.append_to_body(script) def add_toggle_style(self, style=DEFAULT_TOGGLE_STYLE): """Adds a css to format the javascript template, should be done once""" self.append_to_head(style) def add_toggle(self, tag_id=None): """Adds a toggle button that toggles the element with id tag_id. This can be used many times """ toggle = '<input type="button" class="toggleButton" value="+" onclick="toggleId(\'{0}\',this)">'.format(tag_id) self.append_to_body(toggle) def embedd_image(self, image, image_mode="MatplotlibFigure", **options): """Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values""" # might change this to self.ImageGraph and use it elsewhere image_graph = ImageGraph() image_graph.set_state(image_mode, image) image_graph.move_to_node("EmbeddedHtml") self.append_to_body(image_graph.data) def embedd_image_figure(self, image, image_mode="MatplotlibFigure", figure_id="image", caption="", style="", **options): """Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values. The image is in a <figure id=figure_id> tag""" # might change this to self.ImageGraph and use it elsewhere image_graph = ImageGraph() image_graph.set_state(image_mode, image) image_graph.move_to_node("EmbeddedHtml") self.append_to_body("<figure id='{0}' style='{3}'>{1}<figcaption>{2}</figcaption></figure>".format(figure_id, image_graph.data, caption, style)) def add_download_link(self, content_string, text="Download File", suggested_name="test.txt", mime_type="text/plain"): """Adds a download link to the report""" self.append_to_body(String_to_DownloadLink(content_string, text=text, suggested_name=suggested_name, mime_type=mime_type)) def clear(self): """Clears all content in the HTML""" element_list = self.root.getchildren() for child in element_list: self.root.remove(child)
Ancestors (in MRO)
- HTMLReport
- Code.DataHandlers.HTMLModels.HTMLBase
- __builtin__.object
Methods
def __init__(
self, file_path=None, **options)
Intializes the HTMLBase Class
def __init__(self,file_path=None,**options): """Intializes the HTMLBase Class""" defaults={"specific_descriptor":'HTML', "general_descriptor":'Document', "directory":None, "extension":'html', "path":None, "html_text":None, "body":None, "head":None } self.options={} for key,value in defaults.items(): self.options[key]=value for key,value in options.items(): self.options[key]=value # Define Method Aliases if they are available if METHOD_ALIASES: for command in alias(self): exec(command) if file_path is None: # create self.document if self.options["html_text"]: # first priority is just passing the full page in html_text self.document=lxml.html.fromstring(self.options["html_text"]) self.root=self.document else: self.root=lxml.html.builder.HTML() self.document=lxml.etree.ElementTree(self.root) elements=["head","body"] for element in elements: if self.options[element]: if isinstance(element, StringType): new_element=lxml.html.fragment_fromstring(self.options[element]) self.root.append(new_element) elif isinstance(element, lxml.html.Element): self.root.append(self.options[element]) self.text=str(self) if self.options["path"]: self.path=self.options["path"] else: self.path=auto_name(specific_descriptor=self.options["specific_descriptor"], general_descriptor=self.options["general_descriptor"], directory=self.options["directory"], extension=self.options["extension"]) else: self.path=file_path self.document=lxml.html.parse(file_path) try: self.root=self.document.getroot() except:pass try: self.head=self.root.head except:pass try: self.body=self.root.body except:pass
def add_body(
self)
Adds a body tag to the model if it does not exist
def add_body(self): """Adds a body tag to the model if it does not exist""" body=make_html_element(tag="body",text="") tags=[x.tag.lower() for x in self.root.getchildren()] if not "body" in tags: self.root.append(body) else: print("body already exists, tag was not added ") pass self.body=self.root.body
def add_download_link(
self, content_string, text='Download File', suggested_name='test.txt', mime_type='text/plain')
Adds a download link to the report
def add_download_link(self, content_string, text="Download File", suggested_name="test.txt", mime_type="text/plain"): """Adds a download link to the report""" self.append_to_body(String_to_DownloadLink(content_string, text=text, suggested_name=suggested_name, mime_type=mime_type))
def add_head(
self)
Adds a head tag to the model if it does not exist
def add_head(self): """Adds a head tag to the model if it does not exist""" head=make_html_element(tag="head",text="") if len(self.root.getchildren())==0: self.root.append(head) elif not re.match("head",self.root.getchildren()[0].tag,re.IGNORECASE) and len(self.root.getchildren())>0: self.root.insert(0,head) else: print("head already exists, tag was not added ") self.head=self.root.head
def add_toggle(
self, tag_id=None)
Adds a toggle button that toggles the element with id tag_id. This can be used many times
def add_toggle(self, tag_id=None): """Adds a toggle button that toggles the element with id tag_id. This can be used many times """ toggle = '<input type="button" class="toggleButton" value="+" onclick="toggleId(\'{0}\',this)">'.format(tag_id) self.append_to_body(toggle)
def add_toggle_script(
self, script='<script type="text/javascript">\n function toggleId(id,$link){\n $node = document.getElementById(id);\n if (!$node)\n return;\n if (!$node.style.display || $node.style.display == \'none\') {\n $node.style.display = \'block\';\n $link.value = \'-\';\n } else {\n $node.style.display = \'none\';\n $link.value = \'+\';\n }\n }\n </script>')
Adds a javascript template toggle script to the body of the HTML
def add_toggle_script(self, script=DEFAULT_TOGGLE_SCRIPT): """Adds a javascript template toggle script to the body of the HTML""" self.append_to_body(script)
def add_toggle_style(
self, style='<style>\n .toggleButton {\n background-color: white;\n border: 2px solid black;\n border-radius: 8px;\n color:red;\n\t }\n .toggleButton:hover {\n box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);\n\t}\n </stlye>')
Adds a css to format the javascript template, should be done once
def add_toggle_style(self, style=DEFAULT_TOGGLE_STYLE): """Adds a css to format the javascript template, should be done once""" self.append_to_head(style)
def append_to_body(
self, element)
Appends the element to the body of the model, if it is a string it parses first, if it is a dictionary it assumes it has the form {"tag":tag_name,"text":text_text, "attribute_dictionary":{"attribute_name":"attribute_value"}, and if it is a lxml.html.HtmlElement it appends it
def append_to_body(self,element): """Appends the element to the body of the model, if it is a string it parses first, if it is a dictionary it assumes it has the form {"tag":tag_name,"text":text_text, "attribute_dictionary":{"attribute_name":"attribute_value"}, and if it is a lxml.html.HtmlElement it appends it""" try: tags = [x.tag.lower() for x in self.root.getchildren()] if not "body" in tags: body = make_html_element(tag="body", text="") print("Body tag was not present adding it") self.root.append(body) if isinstance(element, StringType): new_element=lxml.html.fragment_fromstring(element) elif isinstance(element, DictionaryType): new_element=make_html_element(**element) elif isinstance(element,lxml.html.HtmlElement): new_element=element self.root.body.append(new_element) except: print(("Could not add {0} to body".format(element)))
def append_to_head(
self, element)
Appends the element to the head of the model, if it is a string it parses first, if it is a dictionary it assumes it has the form {"tag":tag_name,"text":text_text, "attribute_dictionary":{"attribute_name":"attribute_value"}, and if it is a lxml.html.HtmlElement it appends it
def append_to_head(self,element): """Appends the element to the head of the model, if it is a string it parses first, if it is a dictionary it assumes it has the form {"tag":tag_name,"text":text_text, "attribute_dictionary":{"attribute_name":"attribute_value"}, and if it is a lxml.html.HtmlElement it appends it""" try: tags = [x.tag.lower() for x in self.root.getchildren()] if not "head" in tags: head = make_html_element(tag="head", text="") print("Head tag was not present adding it") self.root.insert(0,head) if isinstance(element, StringType): new_element=lxml.html.fragment_fromstring(element) elif isinstance(element, DictionaryType): new_element=make_html_element(**element) elif isinstance(element,lxml.html.HtmlElement): new_element=element self.root.head.append(new_element) except: print(("Could not add {0} to head".format(element)))
def clear(
self)
Clears all content in the HTML
def clear(self): """Clears all content in the HTML""" element_list = self.root.getchildren() for child in element_list: self.root.remove(child)
def embedd_image(
self, image, image_mode='MatplotlibFigure', **options)
Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values
def embedd_image(self, image, image_mode="MatplotlibFigure", **options): """Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values""" # might change this to self.ImageGraph and use it elsewhere image_graph = ImageGraph() image_graph.set_state(image_mode, image) image_graph.move_to_node("EmbeddedHtml") self.append_to_body(image_graph.data)
def embedd_image_figure(
self, image, image_mode='MatplotlibFigure', figure_id='image', caption='', style='', **options)
Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values. The image is in a
def embedd_image_figure(self, image, image_mode="MatplotlibFigure", figure_id="image", caption="", style="", **options): """Embedds an image in the report. image_mode can be MatplotlibFigure (a reference to the figure class), Image (the PIL class), Base64 (a string of the values), Png, Jpg, Bmp Tiff(the file name), or a Ndarray of the image values. The image is in a <figure id=figure_id> tag""" # might change this to self.ImageGraph and use it elsewhere image_graph = ImageGraph() image_graph.set_state(image_mode, image) image_graph.move_to_node("EmbeddedHtml") self.append_to_body("<figure id='{0}' style='{3}'>{1}<figcaption>{2}</figcaption></figure>".format(figure_id, image_graph.data, caption, style))
def save(
self, file_path=None, **temp_options)
Saves the html file, provide file path to save as, or temp_options
def save(self,file_path=None,**temp_options): """Saves the html file, provide file path to save as, or temp_options""" original_options=self.options.copy() for key,value in temp_options.items(): self.options[key]=value if file_path is None: file_path=self.path out_file=open(file_path,"w") out_file.write(str(self)) out_file.close() self.options=original_options return file_path
def show(
self)
Saves html to a temp file and shows it in a browser
def show(self): """Saves html to a temp file and shows it in a browser""" lxml.html.open_in_browser(self.document)
def to_HTML(
self)
Convenience function that echos the content updates the attribute self.text
def to_HTML(self): """Convenience function that echos the content updates the attribute self.text""" self.text=str(self) return str(self.text)
def to_pdf(
self, file_path=None, **options)
Converts the file to a pdf and saves it at file_path. If file_path is None, it will auto name the resulting file to self.path with pdf as the extension
def to_pdf(self,file_path=None,**options): """Converts the file to a pdf and saves it at file_path. If file_path is None, it will auto name the resulting file to self.path with pdf as the extension""" #todo: add toc and other options in wkhtmltopdf if file_path is None: file_path=change_extension(self.path,"pdf") config = pdfkit.configuration(wkhtmltopdf=WKHTML_PATH) pdfkit.from_string(str(self),file_path,configuration=config) return file_path
Module variables
var COMBINED_ONE_PORT_CHKSTD_CSV
var COMBINED_POWER_CHKSTD_CSV
var COMBINED_TWO_PORT_CHKSTD_CSV
var COMBINE_S11_S22
var COMMENT_PATTERN
var CONNECTOR_TYPES
var CONVERT_S21
var DEFAULT_FILE_NAME
var DEFAULT_INSTRUMENT_SHEET_STYLE
var DEFAULT_INSTRUMENT_STATE_STYLE
var DEFAULT_LOG_STYLE
var DEFAULT_MEASUREMENT_STYLE
var DEFAULT_METADATA_STYLE
var DEFAULT_REGISTER_STYLE
var DEFAULT_STYLE
var DEFAULT_TOGGLE_SCRIPT
var DEFAULT_TOGGLE_STYLE
var DRIVER_FILE_EXTENSIONS
var DUT_COLUMN_NAMES
var EXIF_AVAILABLE
var EXTENSION_PATTERN
var FORMATS
var FREQUENCY_UNITS
var GENERAL_DESCRIPTORS
var GET_STATS_FIELDS
var HTML_TEMPLATE_DIRECTORY
var IMAGE_FILE_EXTENSIONS
var INKSCAPE_PATH
var INSTRUMENT_SHEETS
var METHOD_ALIASES
var MINIMUM_DB
var MINIMUM_DB_ARG_VALUE
var MINIMUM_DB_VALUE
var NODE_TYPE_DICTIONARY
var NUMBER_MATCH_STRING
var ONE_PORT_CALREP_CSV
var ONE_PORT_COLUMN_NAMES
var ONE_PORT_DTYPE
var ONE_PORT_DUT
var OPTION_LINE_PATTERN
var OS_STAT_FIELDS
var PARAMETERS
var PDF_CONVERT
var PIL_AVAILABLE
var POWER_3TERM_CALREP_CSV
var POWER_3TERM_COLUMN_DESCRIPTIONS
var POWER_3TERM_COLUMN_NAMES
var POWER_4TERM_CALREP_CSV
var POWER_4TERM_COLUMN_DESCRIPTIONS
var POWER_4TERM_COLUMN_NAMES
var PYMEASURE_ROOT
var RESULTS_FILE_ONE_PORT_COLUMN_NAMES
var RESULTS_FILE_POWER_COLUMN_NAMES
var RESULTS_FILE_TWO_PORT_COLUMN_NAMES
var S1P_DB_COLUMN_NAMES
var S1P_MA_COLUMN_NAMES
var S1P_RI_COLUMN_NAMES
var S2P_COMPLEX_COLUMN_NAMES
var S2P_DB_COLUMN_DESCRIPTION
var S2P_DB_COLUMN_NAMES
var S2P_MA_COLUMN_DESCRIPTION
var S2P_MA_COLUMN_NAMES
var S2P_NOISE_PARAMETER_COLUMN_NAMES
var S2P_RI_COLUMN_DESCRIPTION
var S2P_RI_COLUMN_NAMES
var SMITHPLOT
var SOLUTION_VECTOR_COLUMN_NAMES
var StringTypes
var TESTS_DIRECTORY
var TOUCHSTONE_KEYWORDS
var TWELVE_TERM_ERROR_COLUMN_NAMES
var TWO_PORT_CALREP_CSV
var TWO_PORT_NR_CHKSTD_CSV
var WINDOWS_COM
var WINDOWS_WRAPPER
var WKHTML_PATH
var XSLT_CAPABLE
var XSLT_REPOSITORY
var type_names