generatepdf.py 7.84 KB
Newer Older
sarrvesh's avatar
sarrvesh committed
1 2 3 4
"""Functions to generate PDF file"""

from datetime import datetime
import os
sarrvesh's avatar
sarrvesh committed
5
from fpdf import FPDF, HTMLMixin
sarrvesh's avatar
sarrvesh committed
6 7
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
sarrvesh's avatar
sarrvesh committed
8
from matplotlib.patches import Rectangle
sarrvesh's avatar
sarrvesh committed
9

sarrvesh's avatar
sarrvesh committed
10
# Dummy class needed to generate the PDF file
sarrvesh's avatar
sarrvesh committed
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
class MyFPDF(FPDF, HTMLMixin):
    """Dummy class"""
    pass

def convert_figure_to_axis_info(figure):
    """For a given Graph Figure object, return
       xaxis (a list of datetime.datetime objects),
       yaxis (a list of source elevation), and
       label (name of the source as a string)."""
    time_axis = figure['x']
    xaxis = []
    for val in time_axis:
        d = datetime.strptime(val, '%Y-%m-%dT%H:%M:%S')
        xaxis.append(d)
    yaxis = figure['y']
    label = figure['name']
    return xaxis, yaxis, label

def make_pdf_plot(elevation_fig, outfilename):
    """For a given elevation_fig object and output filename, generate a
       matplotlib plot and write it to disk."""
    fig, ax = plt.subplots(1, 1, figsize=(8, 5))
    for figure in elevation_fig['data']:
        xaxis, yaxis, label = convert_figure_to_axis_info(figure)
        ax.plot(xaxis, yaxis, label=label)
    hour_loc = (0, 3, 6, 9, 12, 15, 18, 21)
    ax.xaxis.set_major_locator(mdates.HourLocator(hour_loc))
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))
sarrvesh's avatar
sarrvesh committed
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
    plt.xlabel('Time (UTC)', fontsize=14)
    plt.ylabel('Elevation (deg)', fontsize=14)
    plt.title('Target visibility plot', fontsize=14)

    # Highlight sunrise
    sun_rise_dict = elevation_fig['layout']['shapes'][0]
    temp_date = sun_rise_dict['x0'].split('.')[0]
    x_min = datetime.strptime(temp_date, '%Y-%m-%dT%H:%M:%S')
    temp_date = sun_rise_dict['x1'].split('.')[0]
    x_max = datetime.strptime(temp_date, '%Y-%m-%dT%H:%M:%S')
    y_min = sun_rise_dict['y0']
    y_max = sun_rise_dict['y1']
    rect = Rectangle((x_min, y_min), width=x_max-x_min, height=y_max, fill=True,
                     edgecolor=None, facecolor='lightskyblue')
    ax.add_patch(rect)

    # Highlight sunset
    sun_set_dict = elevation_fig['layout']['shapes'][1]
    temp_date = sun_set_dict['x0'].split('.')[0]
    x_min = datetime.strptime(temp_date, '%Y-%m-%dT%H:%M:%S')
    temp_date = sun_set_dict['x1'].split('.')[0]
    x_max = datetime.strptime(temp_date, '%Y-%m-%dT%H:%M:%S')
    y_min = sun_set_dict['y0']
    y_max = sun_set_dict['y1']
    rect = Rectangle((x_min, y_min), width=x_max-x_min, height=y_max, fill=True,
                     edgecolor=None, facecolor='lightskyblue')
    ax.add_patch(rect)

    plt.ylim([0, 90])
sarrvesh's avatar
sarrvesh committed
68 69

    if len(elevation_fig['data']) > 1:
sarrvesh's avatar
sarrvesh committed
70
        ax.legend(fontsize=14)
sarrvesh's avatar
sarrvesh committed
71 72 73 74 75
    plt.tight_layout()
    plt.savefig(outfilename, dpi=100)

def generate_pdf(pdf_file, obs_t, n_core, n_remote, n_int, n_chan, n_sb, integ_t,
                 antenna_set, pipe_type, t_avg, f_avg, is_dysco, im_noise_val,
sarrvesh's avatar
sarrvesh committed
76
                 raw_size, proc_size, pipe_time, elevation_fig, distance_table,
sarrvesh's avatar
sarrvesh committed
77
                 obs_date, obs_mode, tab_mode, stokes):
sarrvesh's avatar
sarrvesh committed
78 79 80 81 82 83 84 85 86 87 88 89
    """Function to generate a pdf file summarizing the content of the calculator.
       Return nothing."""
    # Create an A4 sheet
    pdf = MyFPDF('P', 'mm', 'A4')
    pdf.add_page()
    pdf.set_font('Arial', '', 16)

    # Generate an html string to be written to the file
    string = '<table border="0" align="left" width="80%">'
    string += '<thead><tr><th width="70%" align="left">Parameter</th>'
    string += '<th width="30%" align="left">Value</th></tr></thead>'
    string += '<tbody>'
sarrvesh's avatar
sarrvesh committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103
    
    if obs_mode == 'Interferometric':
        string += '<tr><td>Observation mode</td>'
        string += '    <td>Interferometric</td></tr>'
    else:
        string += '<tr><td>Observation mode</td>'
        string += '    <td>Beamformed</td></tr>'
        string += '<tr><td>Tied array mode</td>'
        string += '    <td>{}</td></tr>'.format(tab_mode)
        string += '<tr><td>Stokes products to record</td>'
        string += '    <td>{}</td></tr>'.format(stokes)
    
    string += '<tr></tr>'
    
sarrvesh's avatar
sarrvesh committed
104 105 106
    string += '<tr><td>Observation time (in seconds)</td>'
    string += '    <td>{}</td></tr>'.format(obs_t)
    string += '<tr><td>No. of stations</td>'
sarrvesh's avatar
sarrvesh committed
107 108 109 110
    if obs_mode == 'Beamformed' and tab_mode == 'Coherent':
        string += '    <td>({}, {}, {})</td></tr>'.format(n_core, 0, 0)
    else:
        string += '    <td>({}, {}, {})</td></tr>'.format(n_core, n_remote, n_int)
sarrvesh's avatar
sarrvesh committed
111 112 113 114 115 116 117 118 119
    string += '<tr><td>No. of subbands</td>'
    string += '    <td>{}</td></tr>'.format(n_sb)
    string += '<tr><td>No. of channels per subband</td>'
    string += '    <td>{}</td></tr>'.format(n_chan)
    string += '<tr><td>Integration time (in seconds)</td>'
    string += '    <td>{}</td></tr>'.format(integ_t)
    string += '<tr><td>Antenna set</td>'
    string += '    <td>{}</td></tr>'.format(antenna_set)
    string += '<tr></tr>'
sarrvesh's avatar
sarrvesh committed
120 121 122 123 124 125
    if elevation_fig != {}:
        # User has specified at least one source in the target setup
        # Display the observation date in the table
        string += '<tr><td>Observation date</td>'
        string += '    <td>{}</td></tr>'.format(obs_date)
        string += '<tr></tr>'
sarrvesh's avatar
sarrvesh committed
126 127 128 129 130 131 132 133 134 135 136 137
    string += '<tr><td>Pipeline type</td>'
    if pipe_type == 'none':
        string += '    <td>{}</td></tr>'.format('None')
    else:
        string += '    <td>{}</td></tr>'.format('Preprocessing')
        string += '<tr><td>Averaging factor (time, freq)</td>'
        string += '    <td>{}, {}</td></tr>'.format(t_avg, f_avg)
        string += '<tr><td>Dysco compression</td>'
        if is_dysco == 'enable':
            string += '    <td>{}</td></tr>'.format('enabled')
        else:
            string += '    <td>{}</td></tr>'.format('disabled')
sarrvesh's avatar
sarrvesh committed
138 139 140 141
    if obs_mode == 'Interferometric':
        string += '<tr></tr>'
        string += '<tr><td>Theoretical image sensitivity (uJy/beam)</td>'
        string += '    <td>{}</td></tr>'.format(im_noise_val)
sarrvesh's avatar
sarrvesh committed
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
    string += '<tr><td>Raw data size (in GB)</td>'
    string += '    <td>{}</td></tr>'.format(raw_size)
    if pipe_type != 'none':
        string += '<tr><td>Processed data size (in GB)</td>'
        string += '    <td>{}</td></tr>'.format(proc_size)
        string += '<tr><td>Pipeline processing time (in hours)</td>'
        string += '    <td>{}</td></tr>'.format(pipe_time)
    string += '</tbody>'
    string += '</table>'

    # Generate a matplotlib plot showing the same plot as in the target
    # visibility plot
    if elevation_fig != {}:
        # User has specified at least one source in the target setup
        png_file_name = pdf_file.replace('summary', 'plot').replace('pdf', 'png')
        make_pdf_plot(elevation_fig, png_file_name)
        # Add the elevation plot to html
        string += '<center>'
        string += '<img src={} width=400 height=250>'.format(png_file_name)
        string += '</center>'
162

sarrvesh's avatar
sarrvesh committed
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
    # Add the distance table to the PDF
    if distance_table != {}:
        title = distance_table['layout']['title']
        string += '<center><b>{}</b></center>'.format(title)
        string += '<table border="0" align="left" width="80%">'
        col_titles = distance_table['data'][0]['header']['values']
        col_width = 100//len(col_titles)
        string += '<thead><tr>'
        for item in col_titles:
            string += '<th width="{}%" align="left">'.format(col_width) + \
                      item + '</th>'
        string += '</tr></thead>'
        string += '<tbody>'
        tab_data = distance_table['data'][0]['cells']['values']
        # Transpose tab_data and write cells to the table
        tab_data = list(map(list, zip(*tab_data)))
        for row in tab_data:
            string += '<tr>'
            for item in row:
                string += '<td>{}</td>'.format(item)
            string += '</tr>'
        string += '</tbody>'
        string += '</table>'
sarrvesh's avatar
sarrvesh committed
186

sarrvesh's avatar
sarrvesh committed
187 188
    # Write text to the pdf file
    pdf.write_html(string)
sarrvesh's avatar
sarrvesh committed
189

sarrvesh's avatar
sarrvesh committed
190 191
    # Write the pdf to disk
    pdf.output(pdf_file)
sarrvesh's avatar
sarrvesh committed
192

sarrvesh's avatar
sarrvesh committed
193 194 195
    # Remove the temporary PNG file from disk
    if elevation_fig != {}:
        os.remove(png_file_name)