Beispiel #1
0
def table_days(days, entity, time_ent=''):
    html = ''
    total = np.size(days, axis=0)
    if total > 0:
        # Time th cell yess or no
        b_time_cell  = True if time_ent != '' else False
        th_time_cell = '<th>time</th>' if b_time_cell else ''
        time_ndx = daydata.ndx_ent(time_ent) if b_time_cell else -1
        val_ndx  = daydata.ndx_ent(entity) # Index of value

        # HTML table header
        html += f'''
                <table class="popup">
                    <thead>
                        <tr>
                            <th>pos</th>
                            <th>date</th>
                            <th>val</th>
                            {th_time_cell}
                        </tr>
                    </thead>
                    <tbody>
                '''

        pos, max = 1, cfg.html_popup_table_val_10
        if max == -1:
            max = total

        for day in days:
            ymd  = int(day[daydata.YYYYMMDD]) # Get data int format
            symd = utils.ymd_to_txt( ymd ) # Get date string format
            val = fix.ent( day[val_ndx], entity )  # Get value with right output

            # Get a time value or not
            time_val = f'<td>{fix.ent(day[time_ndx], time_ent)}</td>' if b_time_cell else ''

            html += f'''
                        <tr>
                            <td>{pos}</td>
                            <td title="{symd}">{ymd}</td>
                            <td>{val}</td>
                            {time_val}
                        </tr>
                    '''
            if pos == max:
                break
            else:
                pos += 1

        html += '''
                </tbody>
            </table>
                '''
    return html
Beispiel #2
0
def table_days_count(days, entity, time_ent=''):
    html = ''
    total = np.size(days, axis=0)
    if total > 0:
        # Time th cell yess or no
        b_time_cell  = True if time_ent != '' else False
        th_time_cell = '<th>time</th>' if b_time_cell else ''
        time_ndx = daydata.ndx_ent( time_ent ) if b_time_cell else -1
        val_ndx  = daydata.ndx_ent( entity )  # Index of value

        html += f'''
                <table class="popup">
                    <thead>
                        <tr>
                            <th>date</th>
                            <th>val</th>
                            {th_time_cell}
                            <th>cnt</th>
                        </tr>
                    </thead>
                    <tbody>
                '''

        pos, max = 1, cfg.html_popup_table_cnt_rows
        if max == -1:
            max = total

        days = np.flip(days, axis=0) # Reverse the matrix. Last day first
        for day in days:
            ymd  = int(day[daydata.YYYYMMDD])
            symd = utils.ymd_to_txt( ymd )
            val  = fix.ent( day[val_ndx], entity )
            tme  = f'<td>{fix.ent(day[time_ndx],time_ent)}</td>' if b_time_cell else ''
            html += f'''
                        <tr>
                            <td title="{symd}">{ymd}</td>
                            <td>{val}</td>
                            {tme}
                            <td>{total}</td>
                        </tr>
                    '''
            if pos == max:
                break
            else:
                total, pos = total - 1, pos + 1

        html += '''
                    </tbody>
                </table>
                '''

    return html
def calculate(places, year, type, fname):
    '''Function calculates year extremes statistics'''
    colspan = 15

    # Make data list with station and year statistics
    yearextremes = list()
    for place in places:
        console.log(f'Process extremes {place.place} for the year {year}...',
                    True)
        ok, data = daydata.read(place)  # Get data stations
        if ok:
            days = daydata.period(data,
                                  f'{year}****')  # Get the days in period
            if days.size != 0:  # Skip station if not
                yearextremes.append(Stats(place, days,
                                          year))  # Create yearstats object

    console.log(f'\nPreparing output: {type}', True)

    # Make path if it is a html or txt file
    dir = utils.mk_path(cfg.dir_yearextremes, type)
    path = utils.mk_path(dir, f'{fname}.{type}')
    fio.mk_dir(dir)

    # Sort on TG
    # dayextremes = sort( dayextremes, '+' )

    # Make output
    title, main, footer = '', '', ''

    # Maak content op basis van type uitvoer html of text
    # Maak titel
    table_title = f'Extremes '
    if type in ['txt', 'cmd']:
        pass

    elif type == 'html':
        title += f'''
            <table id="stats">
            <thead>
                <tr>
                    <th colspan="{colspan}">
                        {icon.weather_all()}
                        {table_title}
                        {icon.wave_square()}
                        {year}
                        {icon.cal_period()}
                    </th>
                </tr>
                <tr>
                    <th title="copyright data_notification"> </th>
                    <th> place {icon.home(size='fa-sm')} </th>
                    <th> province {icon.flag(size='fa-sm')} </th>
                    <th> period  {icon.cal_period(size='fa-sm')} </th>
                    <th> year  {icon.cal_period(size='fa-sm')} </th>
                    <th title="Highest maximum temperature"> tx {icon.arrow_up(size='fa-sm')} </th>
                    <th title="Lowest maximum temperature"> tx {icon.arrow_down(size='fa-sm')} </th>
                    <th title="Highest mean temperature"> tg {icon.arrow_up(size='fa-sm')} </th>
                    <th title="Lowest mean temperature"> tg {icon.arrow_down(size='fa-sm')} </th>
                    <th title="Highest minimum temperature"> tn {icon.arrow_up(size='fa-sm')} </th>
                    <th title="Lowest minimum temperature"> tn {icon.arrow_down(size='fa-sm')} </th>
                    <th title="Highest ground minimum temperature"> tn10 {icon.arrow_up(size='fa-sm')} </th>
                    <th title="Lowest ground minimum temperature"> tn10 {icon.arrow_down(size='fa-sm')} </th>
                    <th title="Maximum sunshine"> sq {icon.arrow_up(size='fa-sm')} </th>
                    <th title="Maximum rain"> rh {icon.arrow_up(size='fa-sm')} </th>
                </tr>
            </thead>
            <tbody>
            '''

    # Walkthrough all cities
    for s in yearextremes:
        console.log(f'Make {type} output for: {s.station.place}', True)
        tx_max = fix.ent(s.tx_max, 'TX')
        tx_min = fix.ent(s.tx_min, 'TX')
        tg_max = fix.ent(s.tg_max, 'TG')
        tg_min = fix.ent(s.tg_min, 'TG')
        tn_max = fix.ent(s.tn_max, 'TN')
        tn_min = fix.ent(s.tn_min, 'TN')
        tn10_max = fix.ent(s.tn10_max, 'T10N')
        tn10_min = fix.ent(s.tn10_min, 'T10N')
        sq_max = fix.ent(s.sq_max, 'SQ')
        rh_max = fix.ent(s.rh_max, 'RH')

        if type == 'html':
            period_txt = f'{utils.ymd_to_txt(s.p_start)} - {utils.ymd_to_txt(s.p_end)}'
            main += f'''
                <tr>
                    <td title="{s.station.data_notification.lower()}">
                        {icon.copy_light(size='fa-xs')}
                    </td>
                    <td>
                        <span class="val"> {s.station.place} </span>
                    </td>
                    <td>
                        <span class="val"> {s.station.province} </span>
                    </td>
                    <td title="{period_txt}">
                        <span class="val"> {s.period} </span>
                    </td>
                    <td title="The year is {year}">
                        <span class="val"> {year} </span>
                    </td>
                    <td>
                        <span class="val"> {tx_max} </span>
                        {html.table_days( s.tx_max_sort, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {tx_min} </span>
                        {html.table_days(np.flip(s.tx_max_sort, axis=0), 'TX', 'TXH')}
                    </td>
                    <td>
                        <span class="val"> {tg_max} </span>
                        {html.table_days( s.tg_max_sort, 'TG' )}
                    </td>
                    <td>
                        <span class="val"> {tg_min} </span>
                        {html.table_days(np.flip(s.tg_max_sort, axis=0), 'TG' )}
                    </td>
                    <td>
                        <span class="val"> {tn_max} </span>
                        {html.table_days(s.tn_max_sort, 'TN', 'TNH')}
                    </td>
                    <td>
                        <span class="val"> {tn_min} </span>
                        {html.table_days(np.flip(s.tn_max_sort, axis=0), 'TN', 'TNH')}
                    </td>
                    <td>
                        <span class="val"> {tn10_max} </span>
                        {html.table_days(s.tn10_max_sort, 'T10N', 'T10NH')}
                    </td>
                    <td>
                        <span class="val"> {tn10_min} </span>
                        {html.table_days(np.flip(s.tn10_max_sort, axis=0), 'T10N', 'T10NH')}
                    </td>
                    <td>
                        <span class="val"> {sq_max} </span>
                        {html.table_days(s.sq_max_sort, 'SQ')}
                    </td>
                    <td>
                        <span class="val"> {rh_max} </span>
                        {html.table_days(s.rh_max_sort, 'RH')}
                    </td>
                </tr>
                '''

    if type in ['txt', 'cmd']:
        footer += cfg.knmi_dayvalues_notification

    if type == 'html':
        footer += f'''
            </tbody>
            <tfoot>
                <tr>
                    <td colspan="{colspan}">
                        {utils.now_created_notification()}
                    </td>
                </tr>
            </tfoot>
        </table>
        '''

    path_to_root = './../../'  # Path to html root
    console.log('\nWrite/print results... ', True)

    # Write to file or console
    output = f'{title}\n{main}\n{footer}'
    if type == 'cmd':
        console.log(output, True)

    elif type == 'html':
        page = html.Template()
        page.title = table_title
        page.main = output
        page.strip = True
        page.path_to_root = path_to_root
        page.file_path = path

        # Styling
        page.css_files = [
            f'{path_to_root}yearextremes/css/default.css',
            f'{path_to_root}static/css/table-statistics.css',
            f'{path_to_root}yearextremes/css/yearextremes.css'
        ]
        # Scripts
        page.script_files = [
            f'{path_to_root}yearextremes/js/yearextremes.js',
            f'{path_to_root}static/js/sort-col.js',
            f'{path_to_root}static/js/default.js'
        ]
        page.save()

    elif type == 'txt':
        fio.save(path, output)  # Schrijf naar bestand

    return path
Beispiel #4
0
def plot( stations, ent_type_graphs, period, title, ylabel, fname, options ):

    path = utils.mk_path( cfg.dir_period_img, fname + f'.{cfg.plot_image_type}' )

    # Size values are inches. And figure always in front
    plt.figure( figsize=( convert.pixel_to_inch(options['plot_width']),
                          convert.pixel_to_inch(options['plot_height'])
                          ), dpi=options['plot_dpi'] )

    # Color handling
    rnd_col = True if len(stations) > 1 else False
    if rnd_col:
        col_list = utils.shuffle_list(vcol.save_colors, level=2)
        col_ndx, col_cnt = 0, len(col_list) - 1

    min, max = 999999.9, -9999999.9

    period_extremes, clima_means = list(), list()
    min_max_ave_sum_txt = False
    min_max_ave_sum_mean_txt = False
    for station in stations:
        # console.log(f'Calculate weatherdata for {station.place}', True)
        ok, data = daydata.read(station)
        if ok:
            days = daydata.period(data, period)
            ymd = days[:, daydata.ndx_ent('YYYYMMDD')].astype(
                            np.int, copy=False ).astype( np.str, copy=False
                            ).tolist() # Convert to list
            s_ymd, e_ymd = ymd[0], ymd[-1]
            sy, sm, sd  = s_ymd[0:4], s_ymd[4:6], s_ymd[6:8]
            ey, em, ed  = e_ymd[0:4], e_ymd[4:6], e_ymd[6:8]

            clima_mean_sub_txt = ''
            for opts in ent_type_graphs:
                ent         = opts[0].upper()
                graph_type  = opts[1]
                line_width  = opts[2]
                marker_size = opts[3]
                marker_text = opts[4]
                min_max_ave = opts[5]
                climate_ave = opts[6]
                climate_ave_marker_txt = opts[7]
                climate_periode = opts[8]
                cs_ymd, ce_ymd = climate_periode.split('-')
                scy, ecy = cs_ymd[0:4], ce_ymd[0:4]
                console.log(f'Process weatherdata {station.place} for {ent}', True)

                # Get the values needed for the graph
                f_val = days[:, daydata.ndx_ent(ent)]
                # console.log(f'{station.place} {ent} data values: {str(f_val)}')

                if utils.is_yes(min_max_ave):
                    min_max_ave_sum_txt = True
                    # Calculate extremes
                    min_per = stats.min(days, ent) # slow
                    max_per = stats.max(days, ent)
                    ave_per = stats.average(days, ent)
                    # Correct output
                    s_max = f'max {fix.ent(max_per, ent)}'
                    s_min = f'min {fix.ent(min_per, ent)}'
                    s_ave = f'mean {fix.ent(ave_per, ent)}'
                    s_ext = f'{ent} ({sy}{sm}{sd}-{ey}{em}{ed})'

                    if ent in ['SQ', 'RH', 'EV24', 'Q']:
                        sum_per = fix.ent(stats.sum(days, ent), ent)
                        s_ext += f'   {s_max}   sum {sum_per}   {s_ave}'
                    else:
                        s_ext += f'   {s_max}   {s_min}   {s_ave}'

                    period_extremes.append( s_ext )
                    console.log(s_ext)

                # Cumulative sum of values, if chosen
                if utils.is_yes(options['plot_cummul_val']):
                    f_val = np.cumsum( f_val )

                # Min/ max for ranges
                min_act = fix.rounding( np.min(f_val), ent )
                max_act = fix.rounding( np.max(f_val), ent )
                if min_act < min:
                    min = min_act
                if max_act > max:
                    max = max_act

                # Make correct output values
                l_val = [ fix.rounding(v, ent) for v in f_val.tolist() ]
                label = f'{station.place} {vt.ent_to_title(ent)}'
                color = col_list[col_ndx] if rnd_col else vcol.ent_to_color(ent)

                if utils.is_yes( climate_ave ):
                    min_max_ave_sum_mean_txt = True
                    label_clima = f'Day climate {station.place} {vt.ent_to_title(ent)}'
                    clima_ymd = days[:, daydata.YYYYMMDD ].tolist()

                    cli_txt = f'Calculate climate value {ent} for {station.place} (might take a while...)'
                    console.log(cli_txt, True)

                    l_clima = []
                    for d in clima_ymd:
                        ds =  utils.f_to_s(d)
                        mmdd = ds[4:8] # What day it is ?
                        sdat = datetime.strptime(ds, '%Y%m%d').strftime('%B %d').lower()
                        val  = stats.climate_average_for_day( station, mmdd, ent, climate_periode )
                        s_clima = fix.rounding(val, ent)
                        console.log(f'Climate value {ent} for {sdat} is {s_clima}')
                        # Append raw data without correct rounding
                        l_clima.append(val)

                    if utils.is_yes(min_max_ave):
                        # Clima average round correctly based on entity
                        if len(l_clima) > 0:
                            # Calculate average
                            sum = 0.0
                            for el in l_clima:
                                sum += el
                            ave = sum / len(l_clima)
                            s_ave = f'Climate mean ({scy}-{ecy}) {ent} is {fix.ent(ave, ent)}'
                            clima_mean_sub_txt = s_ave
                            console.log( s_ave )

                        else:
                            console.log('List with clima values is empthy.')

                    # Round correctly al climate values based on ent
                    for ndx, val in enumerate(l_clima):
                        l_clima[ndx] = fix.rounding( val, ent )

                    console.log(' ')

                if graph_type == 'line':
                    plt.plot(ymd, l_val,
                             label      = label,
                             color      = color,
                             marker     = cfg.plot_marker_type,
                             linestyle  = cfg.plot_line_style,
                             linewidth  = line_width,
                             markersize = marker_size,
                             alpha      = 0.6 )

                    if utils.is_yes(climate_ave):
                        plt.plot(ymd, l_clima,
                                 label = label_clima,
                                 color      = color,
                                 marker     = cfg.plot_clima_marker_type,
                                 linestyle  = cfg.plot_clima_line_style,
                                 linewidth  = line_width,
                                 markersize = marker_size,
                                 alpha      = 0.6 )

                elif graph_type == 'bar':
                    plt.bar( ymd, l_val, label = label, color = color, alpha = 0.5 )

                    if utils.is_yes(climate_ave):
                        plt.bar(ymd, l_clima, label=label_clima, color=color)

                # Marker texts
                diff = 0.2 if graph_type == 'line' else 0.1
                if utils.is_yes(marker_text):
                    # TODO No negative values for when graph is a bar
                    text = l_val

                    for d, v, t in zip( ymd, l_val, text ):
                        plt.text( d, v+diff, t,
                                  color=cfg.plot_marker_color,
                                  **cfg.plot_marker_font,
                                  horizontalalignment=cfg.plot_marker_horizontalalignment,
                                  alpha=cfg.plot_marker_alpha )

                if  utils.is_yes(climate_ave_marker_txt):
                    for d, v, t in zip( ymd, l_clima, l_clima ):
                        plt.text( d, v+diff, t,
                                  color=cfg.plot_marker_color,
                                  **cfg.plot_marker_font,
                                  horizontalalignment=cfg.plot_marker_horizontalalignment,
                                  alpha=cfg.plot_marker_alpha )

                if rnd_col:
                    col_ndx = 0 if col_ndx == col_cnt else col_ndx + 1

            clima_means.append(clima_mean_sub_txt)

        else:
            console.log('Read not oke in graphs.py -> plot')

    max = round(math.ceil(max), 1)
    min = round(math.floor(min), 1)
    # diff_val = max - min
    add_multi = (len(stations) * len(ent_type_graphs)) * 0.08
    add_space = 1.0 + add_multi # Get legend some space above
    max_tick  = math.ceil( max * add_space )  # upperrange extra
    min_tick  = min  #  % underrange extra unused

    # Update steps
    diff_tick = max_tick - min_tick
    step_calc = math.floor( diff_tick / 10 )
    step_end  = 1 if step_calc < 1 else step_calc  # min step = 1
    pos_txt   = max_tick - 0.3  # Under the edge
    yticks    = np.arange( min_tick, max_tick + step_end, step_end )  # 1-10 % ranges
    xticks    = ymd

    # print('max: '       + str(max))
    # print('min: '       + str(min))
    # print('diff_val: '  + str(diff_val))
    # print('add_multi: ' + str(add_multi))
    # print('!add_space: ' + str(add_space))
    # print('max_tick: '  + str(max_tick))
    # print('min_tick: '  + str(min_tick))
    # print('diff_tick: ' + str(diff_tick))
    # print('step_calc: ' + str(step_calc))
    # print('step_end: '  + str(step_end))
    # print('pos_txt: '   + str(pos_txt))
    # print('xticks: '    + str(xticks))
    # print('yticks: '    + str(yticks))
    # input('')

    if min_max_ave_sum_txt:
        # Add min.max/sum
        t = ''
        for el in period_extremes:
            t += el + '\n'
        # Add clima calculations
        if min_max_ave_sum_mean_txt:
            for el in clima_means:
                t += el + '\n'
        # Add text to plot
        plt.text( ymd[0], pos_txt, # Most left and at the top
                  t, **cfg.plot_add_txt_font, color='#555555',
                  horizontalalignment='left', verticalalignment='top' )

    plt.yticks( yticks, **cfg.plot_yas_font, color=cfg.plot_yas_color )
    plt.xticks( xticks, **cfg.plot_xas_font, color=cfg.plot_xas_color,
                rotation=cfg.plot_xas_rotation )
    plt.title( title, **cfg.plot_title_font, color=cfg.plot_title_color )
    plt.xlabel( cfg.plot_xlabel_text, **cfg.plot_xlabel_font, color=cfg.plot_xlabel_color )
    plt.ylabel( ylabel, **cfg.plot_ylabel_font, color=cfg.plot_ylabel_color )
    plt.legend( loc=cfg.plot_legend_loc,
                prop=cfg.plot_legend_font,
                facecolor=cfg.plot_legend_facecolor,
                shadow=cfg.plot_legend_shadow,
                frameon=cfg.plot_legend_frameon,
                fancybox=cfg.plot_legend_fancybox )

    if cfg.plot_grid_on:
        plt.grid( color=cfg.plot_grid_color,
                  linestyle=cfg.plot_grid_linestyle,
                  linewidth=cfg.plot_grid_linewidth )

    if utils.is_yes(cfg.plot_tight_layout):
        plt.tight_layout()

    plt.savefig( path, dpi=options['plot_dpi'], format=options['plot_image_type'] )

    if utils.is_yes(cfg.plot_show):
        plt.show()

    return path
def calculate(stations, period, name=False, type='html'):
    '''Function calculates all statistics'''
    colspan = 33

    # Make data list with station and summerstatistics
    allstats = list()
    for station in stations:
        console.log(f'Calculate statistics: {station.place}', True)
        ok, data = daydata.read(station)  # Get data stations
        if ok:
            days = daydata.period(data, period)  # Get days of period
            if days.size != 0:  # Skip station
                allstats.append(Stats(station,
                                      days))  # Create summerstats object

    console.log(f'\nPreparing output: {type}', True)

    # Update name if there is none yet
    if not name:
        name = utils.mk_name('all-statistics', period)

    # Make path if it is a html or txt file
    dir = utils.mk_path(cfg.dir_allstats, type)
    path = utils.mk_path(dir, f'{name}.{type}')
    fio.mk_dir(dir)

    # Sort on TG
    allstats = sort(allstats, '+')

    # Make output
    title, main, footer = '', '', ''

    # Maak content op basis van type uitvoer html of text
    # Maak titel
    table_title = 'All statistics '
    if type in ['txt', 'cmd']:
        s = ' '
        title += f'{table_title} {period}\n'
        title += f'PLACE{s:15} '
        title += f'PROVINCE{s:7} '
        title += f'PERIOD{s:11} '
        title += f'TG{s:5} '
        title += f'WARMTH '
        title += 'TX MAX  '
        title += 'TG MAX  '
        title += 'TN MAX  '
        title += 'TX≥20 '
        title += 'TX≥25 '
        title += 'TX≥30 '
        title += 'TX≥35 '
        title += 'TX≥40 '
        title += 'TG≥20 '
        title += 'TG≥18 '
        title += 'TN≥20 '
        title += 'ZON≥10 '
        title += 'ZON{s:6} '
        title += 'REGEN≥10 '
        title += 'REGEN\n'

    if type == 'html':
        title += f'''
            <table id="stats">
            <thead>
                <tr>
                    <th colspan="{colspan}">
                        {icon.weather_all()}
                        {table_title}
                        {icon.wave_square()}
                        {period}
                        {icon.cal_period()}
                    </th>
                </tr>
                <tr>
                    <th title="copyright data_notification"> </th>
                    <th> place {icon.home(size='fa-sm')} </th>
                    <th> province {icon.flag(size='fa-sm')} </th>
                    <th> period  {icon.cal_period(size='fa-sm')} </th>
                    <th title="Average temperature"> tg {icon.temp_half(size='fa-sm')} </th>
                    <th title="Highest maximum temperature"> tx {icon.arrow_up(size='fa-sm')} </th>
                    <th title="Highest average temperature"> tg {icon.arrow_up(size='fa-sm')} </th>
                    <th title="Highest minimum temperature"> tn {icon.arrow_up(size='fa-sm')} </th>
                    <th title="Lowest maximum temperature"> tx {icon.arrow_down(size='fa-sm')} </th>
                    <th title="Lowest average temperature "> tg {icon.arrow_down(size='fa-sm')} </th>
                    <th title="Lowest minumum temperature"> tn {icon.arrow_down(size='fa-sm')} </th>
                    <th title="Total hours of sunshine"> {icon.sun(size='fa-sm')} </th>
                    <th title="Total rain mm"> {icon.shower_heavy(size='fa-sm')} </th>
                    <th title="Heat index tg greater than 18 degrees celsius"> heat {icon.fire(size='fa-sm')} </th>
                    <th title="Warm days"> tx{icon.gte(size='fa-xs')}20 </th>
                    <th title="Summer days"> tx{icon.gte(size='fa-xs')}25 </th>
                    <th title="Tropical days"> tx{icon.gte(size='fa-xs')}30 </th>
                    <th title="High tropical days"> tx{icon.gte(size='fa-xs')}35 </th>
                    <th title="High tropical days"> tx{icon.gte(size='fa-xs')}40 </th>
                    <th title="Warm days on average"> tg{icon.gte(size='fa-xs')}18 </th>
                    <th title="Tropical nights"> tn{icon.gte(size='fa-xs')}20 </th>
                    <th title="Days with more than 10hour of sun">
                        {icon.sun(size='fa-xs')}{icon.gte(size='fa-xs')}10h
                    </th>
                    <th title="Days with more than 10 mm of rain">
                        {icon.shower_heavy(size='fa-xs')}{icon.gte(size='fa-xs')}10mm
                    </th>
                    <th title="Hellmann"> hmann {icon.icicles(size='fa-sm')}</th>
                    <th title="IJnsen"> ijnsen {icon.icicles(size='fa-sm')}</th>
                    <th title="Frost sum"> fsum {icon.icicles(size='fa-sm')}</th>
                    <th title="Days with maximum temperature below 0 degrees celsius"> tx{icon.lt(size='fa-xs')}0 </th>
                    <th title="Days with average temperature below 0 degrees celsius"> tg{icon.lt(size='fa-xs')}0 </th>
                    <th title="Days with minimum temperature below 0 degrees celsius"> tn{icon.lt(size='fa-xs')}0 </th>
                    <th title="Days with minimum temperature lower than -5 degrees celsius"> tn{icon.lt(size='fa-xs')}&minus;5 </th>
                    <th title="Days with minimum temperature lower than -10 degrees celsius"> tn{icon.lt(size='fa-xs')}&minus;10 </th>
                    <th title="Days with minimum temperature lower than -15 degrees celsius"> tn{icon.lt(size='fa-xs')}&minus;15 </th>
                    <th title="Days with minimum temperature lower than -20 degrees celsius"> tn{icon.lt(size='fa-xs')}&minus;20 </th>
                </tr>
            </thead>
            <tbody>
            '''

    # Walkthrough all cities
    for s in allstats:
        console.log(f'Make {type} output for: {s.station.place}', True)
        heat_ndx = fix.ent(s.heat_ndx, 'heat_ndx')
        tg_ave = fix.ent(s.tg_ave, 'tg')
        tx_max = fix.ent(s.tx_max, 'tx')
        tg_max = fix.ent(s.tg_max, 'tg')
        tn_max = fix.ent(s.tn_max, 'tn')
        tx_min = fix.ent(s.tx_min, 'tx')
        tg_min = fix.ent(s.tg_min, 'tg')
        tn_min = fix.ent(s.tn_min, 'tn')
        hellmann = fix.ent(s.hellmann, 'hellmann')
        ijnsen = fix.ent(s.ijnsen, 'ijnsen')
        f_sum = fix.ent(s.frost_sum, 'frost_sum')
        sq_sum = fix.ent(s.sq_sum, 'SQ')
        rh_sum = fix.ent(s.rh_sum, 'RH')

        if type in ['txt', 'cmd']:
            main += f'{s.station.place:<21} '
            main += f'{s.station.province:<16} '
            main += f'{s.station.period:<18} '
            main += f'{tg_ave:<7} '
            main += f'{heat_ndx:<7} '
            main += f'{tx_max:<7} '
            main += f'{tg_max:<7} '
            main += f'{tn_max:<7} '
            main += f'{tx_gte_20:^6} '
            main += f'{tx_gte_25:^6} '
            main += f'{tx_gte_30:^6} '
            main += f'{tx_gte_35:^6} '
            main += f'{tg_gte_20:^6} '
            main += f'{tg_gte_18:^6} '
            main += f'{tn_gte_20:^6} '
            main += f'{sq_gte_10:^7} '
            main += f'{sq_tot:<10} '
            main += f'{rh_gte_10:^9} '
            main += f'{rh_tot:<11} '

        if type == 'html':
            period_txt = f'{utils.ymd_to_txt(s.p_start)} - {utils.ymd_to_txt(s.p_end)}'
            main += f'''
                <tr>
                    <td title="{s.station.data_notification.lower()}">
                            {icon.copy_light(size='fa-xs')}
                    </td>
                    <td> <span class="val"> {s.station.place} </span> </td>
                    <td> <span class="val"> {s.station.province} </span> </td>
                    <td title="{period_txt}"> <span class="val"> {s.period} </span> </td>
                    <td>
                        <span class="val"> {tg_ave} </span>
                    </td>
                    <td>
                        <span class="val"> {tx_max} </span>
                        {html.table_days( s.tx_max_sort, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {tg_max} </span>
                        {html.table_days( s.tg_max_sort, 'TG' )}
                    </td>
                    <td>
                        <span class="val"> {tn_max} </span>
                        {html.table_days( s.tn_max_sort, 'TN', 'TNH' )}
                    </td>
                    <td>
                        <span class="val"> {tx_min} </span>
                        {html.table_days( s.tx_min_sort, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {tg_min} </span>
                        {html.table_days( s.tg_min_sort, 'TG' )}
                    </td>
                    <td>
                        <span class="val"> {tn_min} </span>
                        {html.table_days( s.tn_min_sort, 'TN', 'TNH' )}
                    </td>
                    <td>
                        <span class="val"> {sq_sum} </span>
                        {html.table_days( s.sq_sort , 'SQ' )}
                    </td>
                    <td>
                        <span class="val"> {rh_sum} </span>
                        {html.table_days( s.rh_sort, 'RH' )}
                    </td>
                    <td>
                        <span class="val"> {heat_ndx} </span>
                        {html.table_heat_ndx( s.days_heat_ndx, 'TG' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_tx_gte_20, axis=0)} </span>
                        {html.table_days_count(s.days_tx_gte_20, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_tx_gte_25, axis=0)} </span>
                        {html.table_days_count(s.days_tx_gte_25, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_tx_gte_30, axis=0)} </span>
                        {html.table_days_count(s.days_tx_gte_30, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_tx_gte_35, axis=0)} </span>
                        {html.table_days_count(s.days_tx_gte_35, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_tx_gte_40, axis=0)} </span>
                        {html.table_days_count(s.days_tx_gte_40, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_tg_gte_18, axis=0)} </span>
                        {html.table_days_count(s.days_tg_gte_18, 'TG' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_tn_gte_20, axis=0)} </span>
                        {html.table_days_count(s.days_tn_gte_20, 'TG' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_sq_gte_10, axis=0)} </span>
                        {html.table_days_count(s.days_sq_gte_10, 'SQ' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_rh_gte_10, axis=0)} </span>
                        {html.table_days_count(s.days_rh_gte_10, 'RH' )}
                    </td>
                    <td>
                        <span class="val"> {hellmann} </span>
                        {html.table_hellmann( s.days_hellmann )}
                    </td>
                    <td>
                        <span class="val"> {ijnsen} </span>
                    </td>
                    <td>
                        <span class="val"> {f_sum} </span>
                        {html.table_frost_sum( s.frost_sum_data )}
                    </td>
                    <td>
                        <span class="val"> {np.size( s.days_tx_lt_0, axis=0 )} </span>
                        {html.table_days_count( s.days_tx_lt_0, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size( s.days_tg_lt_0, axis=0 )} </span>
                        {html.table_days_count( s.days_tg_lt_0, 'TG' )}
                    </td>
                    <td>
                        <span class="val"> {np.size( s.days_tn_lt_0, axis=0 )} </span>
                        {html.table_days_count( s.days_tn_lt_0, 'TN', 'TNH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size( s.days_tn_lt__5, axis=0 )} </span>
                        {html.table_days_count( s.days_tn_lt__5, 'TN', 'TNH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size( s.days_tn_lt__10, axis=0 )} </span>
                        {html.table_days_count( s.days_tn_lt__10, 'TN', 'TNH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size( s.days_tn_lt__15, axis=0 )} </span>
                        {html.table_days_count( s.days_tn_lt__15, 'TN', 'TNH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size( s.days_tn_lt__20, axis=0 )} </span>
                        {html.table_days_count( s.days_tn_lt__20, 'TN', 'TNH' )}
                    </td>
                </tr>
                '''

    if type in ['txt', 'cmd']:
        footer += cfg.knmi_dayvalues_notification

    if type == 'html':
        footer += f'''
            </tbody>
            <tfoot>
                <tr>
                    <td colspan="{colspan}">
                        {utils.now_created_notification()}
                    </td>
                </tr>
            </tfoot>
            </table>
        '''

    path_to_root = './../../'  # Path to html root
    console.log('\nWrite/print results... ', True)

    # Write to file or console
    output = f'{title}\n{main}\n{footer}'
    if type == 'cmd':
        console.log(output, True)

    elif type == 'html':
        page = html.Template()
        page.title = table_title
        page.main = output
        page.strip = True
        page.path_to_root = path_to_root
        page.file_path = path
        # Styling
        page.css_files = [
            f'{path_to_root}allstats/css/default.css',
            f'{path_to_root}static/css/table-statistics.css',
            f'{path_to_root}allstats/css/allstats.css'
        ]
        # Scripts
        page.script_files = [
            f'{path_to_root}allstats/js/allstats.js',
            f'{path_to_root}static/js/sort-col.js',
            f'{path_to_root}static/js/default.js'
        ]
        page.save()

    elif type == 'txt':
        fio.save(path, output)  # Schrijf naar bestand

    return path
Beispiel #6
0
def ents( day ):
    stn   = utils.f_to_s( day[daydata.STN] )
    ymd   = utils.f_to_s( day[daydata.YYYYMMDD] )
    ddvec = fix.ent(day[daydata.DDVEC], daydata.entities[daydata.DDVEC])
    fhvec = fix.ent(day[daydata.FHVEC], daydata.entities[daydata.FHVEC])
    fg    = fix.ent(day[daydata.FG],  daydata.entities[daydata.FG])
    fhx   = fix.ent(day[daydata.FHX], daydata.entities[daydata.FHX])
    fhxh  = fix.ent(day[daydata.FHXH], daydata.entities[daydata.FHXH])
    fhn   = fix.ent(day[daydata.FHN], daydata.entities[daydata.FHN])
    fhnh  = fix.ent(day[daydata.FHNH], daydata.entities[daydata.FHNH])
    fxx   = fix.ent(day[daydata.FXX], daydata.entities[daydata.FXX])
    fxxh  = fix.ent(day[daydata.FXXH], daydata.entities[daydata.FXXH])
    tg    = fix.ent(day[daydata.TG], daydata.entities[daydata.TG])
    tn    = fix.ent(day[daydata.TN], daydata.entities[daydata.TN])
    tnh   = fix.ent(day[daydata.TNH], daydata.entities[daydata.TNH])
    tx    = fix.ent(day[daydata.TX], daydata.entities[daydata.TX])
    txh   = fix.ent(day[daydata.TXH], daydata.entities[daydata.TXH])
    t10n  = fix.ent(day[daydata.T10N], daydata.entities[daydata.T10N])
    t10nh = fix.ent(day[daydata.T10NH], daydata.entities[daydata.T10NH])
    sq    = fix.ent(day[daydata.SQ], daydata.entities[daydata.SQ])
    sp    = fix.ent(day[daydata.SP], daydata.entities[daydata.SP])
    q     = fix.ent(day[daydata.Q], daydata.entities[daydata.Q])
    dr    = fix.ent(day[daydata.DR], daydata.entities[daydata.DR])
    rh    = fix.ent(day[daydata.RH], daydata.entities[daydata.RH])
    rhx   = fix.ent(day[daydata.RHX], daydata.entities[daydata.RHX])
    rhxh  = fix.ent(day[daydata.RHXH], daydata.entities[daydata.RHXH])
    pg    = fix.ent(day[daydata.PG], daydata.entities[daydata.PG])
    px    = fix.ent(day[daydata.PX], daydata.entities[daydata.PX])
    pxh   = fix.ent(day[daydata.PXH], daydata.entities[daydata.PXH])
    pn    = fix.ent(day[daydata.PN], daydata.entities[daydata.PN])
    pnh   = fix.ent(day[daydata.PNH], daydata.entities[daydata.PNH])
    vvn   = fix.ent(day[daydata.VVN], daydata.entities[daydata.VVN])
    vvnh  = fix.ent(day[daydata.VVNH], daydata.entities[daydata.VVNH])
    vvx   = fix.ent(day[daydata.VVX], daydata.entities[daydata.VVX])
    vvxh  = fix.ent(day[daydata.VVXH], daydata.entities[daydata.VVXH])
    ng    = fix.ent(day[daydata.NG], daydata.entities[daydata.NG])
    ug    = fix.ent(day[daydata.UG], daydata.entities[daydata.UG])
    ux    = fix.ent(day[daydata.UX], daydata.entities[daydata.UX])
    uxh   = fix.ent(day[daydata.UXH], daydata.entities[daydata.UXH])
    un    = fix.ent(day[daydata.UN], daydata.entities[daydata.UN])
    unh   = fix.ent(day[daydata.UNH], daydata.entities[daydata.UNH])
    ev24  = fix.ent(day[daydata.EV24], daydata.entities[daydata.EV24])

    return ( stn, ymd, ddvec, fhvec, fg, fhx,
             fhxh, fhn, fhnh, fxx, fxxh, tg,
             tn, tnh, tx, txh, t10n, t10nh,
             sq, sp, q, dr, rh, rhx,
             rhxh, pg, px, pxh, pn, pnh,
             vvn, vvnh, vvx, vvxh, ng, ug,
             ux, uxh, un, unh, ev24 )
def calculate( stations, period, name=False, type='html' ):
    '''Function calculates summer statistics'''
    colspan = 20

    # Make data list with station and summerstatistics
    summer = list()
    for station in stations:
        console.log(f'Calculate statistics: {station.place}', True)
        ok, data = daydata.read( station )  # Get data stations
        if ok:
            days = daydata.period( data, period ) # Get days of period
            if days.size != 0: # Skip station
                summer.append( Stats( station, days ) ) # Create summerstats object

    console.log(f'\nPreparing output: {type}', True)

    # Update name if there is none yet
    if not name: name = utils.mk_name('summerstatistics', period)

    # Make path if it is a html or txt file
    dir = utils.mk_path(cfg.dir_summerstats, type)
    path = utils.mk_path( dir, f'{name}.{type}' )
    fio.mk_dir(dir)

    # Sort on TG
    summer = sort( summer, '+' )

    # Make output
    title, main, footer = '', '', ''

    # Maak content op basis van type uitvoer html of text
    # Maak titel
    table_title = 'Summer statistics '
    if type in ['txt','cmd']:
        s = ' '
        title += f'{table_title} {period}\n'
        title += f'PLAATS{s:15} '
        title += f'PROVINCIE{s:7} '
        title += f'PERIODE{s:11} '
        title += f'TG{s:5} '
        title += f'WARMTE '
        title += 'TX MAX  '
        title += 'TG MAX  '
        title += 'TN MAX  '
        title += 'TX≥20 '
        title += 'TX≥25 '
        title += 'TX≥30 '
        title += 'TX≥35 '
        title += 'TX≥40 '
        title += 'TG≥20 '
        title += 'TG≥18 '
        title += 'TN≥20 '
        title += 'ZON≥10 '
        title += 'ZON{s:6} '
        title += 'REGEN≥10 '
        title += 'REGEN\n'

    if type == 'html':
        title += f'''
            <table id="stats">
            <thead>
                <tr>
                    <th colspan="{colspan}">
                        {icon.weather_all()}
                        {table_title}
                        {icon.wave_square()}
                        {period}
                        {icon.cal_period()}
                    </th>
                </tr>
                <tr>
                    <th title="copyright data_notification"> </th>
                    <th> place {icon.home(size='fa-sm')}</th>
                    <th> province {icon.flag(size='fa-sm')}</th>
                    <th> period {icon.cal_period(size='fa-sm')}</th>
                    <th title="Average temperature"> tg {icon.temp_half(size='fa-sm')}</th>
                    <th title="Warmte getal"> heat {icon.fire(size='fa-sm')}</th>
                    <th title="Warmste dag"> tx {icon.arrow_up(size='fa-sm')}</th>
                    <th title="Hoogste gemiddelde"> tg {icon.arrow_up(size='fa-sm')}</th>
                    <th title="Hoogste minimum"> tn {icon.arrow_up(size='fa-sm')}</th>
                    <th title="Aantal warme dagen"> tx{icon.gte(size='fa-xs')}20 </th>
                    <th title="Aantal zomers dagen"> tx{icon.gte(size='fa-xs')}25 </th>
                    <th title="Aantal tropische dagen"> tx{icon.gte(size='fa-xs')}30 </th>
                    <th title="Aantal tropische dagen"> tx{icon.gte(size='fa-xs')}35 </th>
                    <th title="Aantal tropische dagen"> tx{icon.gte(size='fa-xs')}40 </th>
                    <th title="Aantal tropennachten"> tn{icon.gte(size='fa-xs')}20 </th>
                    <th title="Warmte getal dagen"> tg{icon.gte(size='fa-xs')}18 </th>
                    <th title="Totaal aantal uren zon"> {icon.sun(size='fa-sm')} </th>
                    <th title="Dagen met meer dan tien uur zon"> {icon.sun(size='fa-xs')}{icon.gte(size='fa-xs')}10h</th>
                    <th title="Totaal aantal mm regen">{icon.shower_heavy(size='fa-sm')}</th>
                    <th title="Dagen met meer dan tien mm regen"> {icon.shower_heavy(size='fa-xs')}{icon.gte(size='fa-xs')}10mm</th>
                </tr>
            </thead>
            <tbody>
            '''

    # Walkthrough all cities
    for s in summer:
        console.log(f'Make {type} output for: {s.station.place}', True)
        heat   = fix.ent( s.heat_ndx, 'heat_ndx' )
        tg_gem = fix.ent( s.tg_gem, 'tg' )
        tx_max = fix.ent( s.tx_max, 'tx' )
        tg_max = fix.ent( s.tg_max, 'tg' )
        tn_max = fix.ent( s.tn_max, 'tn' )
        rh_tot = fix.ent( s.rh_tot, 'rh' )
        sq_tot = fix.ent( s.sq_tot, 'sq' )

        if type in ['txt','cmd']:
            main += f'{s.station.place:<21} '
            main += f'{s.station.province:<16} '
            main += f'{s.station.period:<18} '
            main += f'{tg_gem:<7} '
            main += f'{heat_ndx:<7} '
            main += f'{tx_max:<7} '
            main += f'{tg_max:<7} '
            main += f'{tn_max:<7} '
            main += f'{tx_gte_20:^6} '
            main += f'{tx_gte_25:^6} '
            main += f'{tx_gte_30:^6} '
            main += f'{tx_gte_35:^6} '
            main += f'{tg_gte_20:^6} '
            main += f'{tg_gte_18:^6} '
            main += f'{tn_gte_20:^6} '
            main += f'{sq_gte_10:^7} '
            main += f'{sq_tot:<10} '
            main += f'{rh_gte_10:^9} '
            main += f'{rh_tot:<11} '

        if type == 'html':
            period_txt = f'{utils.ymd_to_txt(s.date_s)} - {utils.ymd_to_txt(s.date_e)}'
            main += f'''
                    <td title="{s.station.data_notification.lower()}">
                            {icon.copy_light(size='fa-xs')}
                    </td>
                    <td> <span class="val"> {s.station.place} </span> </td>
                    <td> <span class="val"> {s.station.province} </span> </td>
                    <td title="{period_txt}"> <span class="val"> {s.period} </span> </td>
                    <td> <span class="val"> {tg_gem} </span> </td>
                    <td>
                        <span class="val"> {heat} </span>
                        {vhtml.table_heat_ndx(s.days_heat_ndx, 'TG')}
                    </td>
                    <td>
                        <span class="val"> {tx_max} </span>
                        {vhtml.table_days( s.tx_max_sort, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {tg_max} </span>
                        {vhtml.table_days( s.tg_max_sort, 'TG' )}
                    </td>
                    <td>
                        <span class="val"> {tn_max}  </span>
                        {vhtml.table_days( s.tn_max_sort, 'TN', 'TNH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_tx_gte_20, axis=0)} </span>
                        {vhtml.table_days_count(s.days_tx_gte_20, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_tx_gte_25, axis=0)} </span>
                        {vhtml.table_days_count(s.days_tx_gte_25, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_tx_gte_30, axis=0)} </span>
                        {vhtml.table_days_count(s.days_tx_gte_30, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_tx_gte_35, axis=0)} </span>
                        {vhtml.table_days_count(s.days_tx_gte_35, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_tx_gte_40, axis=0)} </span>
                        {vhtml.table_days_count(s.days_tx_gte_40, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_tn_gte_20, axis=0)} </span>
                        {vhtml.table_days_count(s.days_tn_gte_20, 'TG' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_tg_gte_18, axis=0)} </span>
                        {vhtml.table_days_count(s.days_tg_gte_18, 'TG' )}
                    </td>
                    <td>
                        <span class="val"> {sq_tot} </span>
                        {vhtml.table_days( s.sq_sort, 'SQ' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_sq_gte_10, axis=0)} </span>
                        {vhtml.table_days_count(s.days_sq_gte_10, 'SQ', '' )}
                    </td>
                    <td>
                        <span class="val"> {rh_tot} </span>
                        {vhtml.table_days( s.rh_sort, 'RH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size(s.days_rh_gte_10, axis=0)} </span>
                        {vhtml.table_days_count(s.days_rh_gte_10, 'RH', '' )}
                    </td>
                </tr>
                '''

    if type in ['txt','cmd']:
        footer += stations[0].data_notification

    if type == 'html':
        footer += f'''
            </tbody>
            <tfoot>
                <tr>
                    <td colspan="{colspan}">
                        {utils.now_created_notification()}
                    </td>
                </tr>
            </tfoot>
            </table>
        '''

    console.log('\nWrite/print results... ', True)
    path_to_root = './../../' # Path to html root

    # Write to file or console
    output = f'{title}\n{main}\n{footer}'
    if type == 'cmd':
        console.log( output, True )

    elif type == 'html':
        page           =  vhtml.Template()
        page.title     =  table_title
        page.main      =  output
        page.strip     =  True
        page.path_to_root = path_to_root
        page.file_path = path
        # Styling
        page.css_files = [ f'{path_to_root}summerstats/css/default.css',
                           f'{path_to_root}static/css/table-statistics.css',
                           f'{path_to_root}summerstats/css/summerstats.css' ]
        # Scripts
        page.script_files = [ f'{path_to_root}summerstats/js/summerstats.js',
                              f'{path_to_root}static/js/sort-col.js',
                              f'{path_to_root}static/js/default.js' ]
        page.save()

    elif type == 'txt':
        fio.save(path, output) # Schrijf naar bestand

    return path
def calculate(stations, period, name, type='html'):
    '''Function to calculate winterstatistics'''
    console.log(f'Preparing output...')
    colspan = 20

    # Make data list with station and stats
    winter = list()
    for station in stations:
        console.log(f'Calculate statistics: {station.place}', True)
        ok, data = daydata.read(station)  # Get data stations
        if ok:
            days = daydata.period(data, period)  # Get days of period
            if days.size != 0:
                winter.append(Stats(station,
                                    days))  # Create winterstats object

    console.log(f'\nPreparing output: {type}', True)

    # Update name if there is none yet
    if not name:
        name = utils.mk_name('winterstatistics', period)

    # Make path if it is a html or txt file
    dir = utils.mk_path(cfg.dir_winterstats, type)
    path = utils.mk_path(dir, f'{name}.{type}')
    fio.mk_dir(dir)

    # Sort on hellmann
    winter = sort(winter, '+')

    # Make output
    title, main, footer = '', '', ''

    # Head of txt of console
    table_title = 'Winter statistics '
    if type in ['txt', 'cmd']:
        title += f'{table_title} {period}\n'
        title += f'PLAATS{s:17} '
        title += f'PROVINCIE{s:8} '
        title += f'PERIODE{s:11} '
        title += f'TG{s:5} '
        title += 'HELLMANN TX MIN  TG MIN  TN MIN  TX<0  TG<0  TN<0  TN<-5  '
        title += 'TX<-10 TX<-15 TX<-20\n'

    if type == 'html':
        title += f'''
              <table id="stats">
              <thead>
                  <tr>
                    <th colspan="{colspan}">
                      {icon.weather_all()}
                      {table_title}
                      {icon.wave_square()}
                      {period}
                      {icon.cal_period()}
                    </th>
                  </tr>
                  <tr>
                    <th title="copyright data_notification"> &nbsp; </th>
                    <th> place {icon.home(size='fa-sm')}</th>
                    <th> province {icon.flag(size='fa-sm')}</th>
                    <th> period {icon.cal_period(size='fa-sm')}</th>
                    <th title="Average temperature"> tg {icon.temp_half(size='fa-sm')}</th>
                    <th title="Hellmann"> hmann {icon.icicles(size='fa-sm')}</th>
                    <th title="IJnsen"> ijnsen {icon.icicles(size='fa-sm')}</th>
                    <th title="Frost sum"> fsum {icon.icicles(size='fa-sm')}</th>
                    <th title="Coldest maximum temperature"> tx {icon.arrow_down(size='fa-sm')}</th>
                    <th title="Coldest average temperature "> tg {icon.arrow_down(size='fa-sm')}</th>
                    <th title="Coldest minumum temperature"> tn {icon.arrow_down(size='fa-sm')}</th>
                    <th title="Total hours sun"> {icon.sun(size='fa-sm')}</th>
                    <th title="Total mm rain"> {icon.shower_heavy(size='fa-sm')} </th>
                    <th title="Days with maximum temperature below 0 degrees celsius"> tx{icon.lt(size='fa-xs')}0 </th>
                    <th title="Days with average temperature below 0 degrees celsius"> tg{icon.lt(size='fa-xs')}0 </th>
                    <th title="Days with minimum temperature below 0 degrees celsius"> tn{icon.lt(size='fa-xs')}0 </th>
                    <th title="Days with temperature lower than -5 degrees celsius"> tn{icon.lt(size='fa-xs')}&minus;5 </th>
                    <th title="Days with temperature lower than -10 degrees celsius"> tn{icon.lt(size='fa-xs')}&minus;10 </th>
                    <th title="Days with temperature lower than -15 degrees celsius"> tn{icon.lt(size='fa-xs')}&minus;15 </th>
                    <th title="Days with temperature lower than -20 degrees celsius"> tn{icon.lt(size='fa-xs')}&minus;20 </th>
                  </tr>
              </thead>
              <tbody>
            '''
    # Calculate values
    for s in winter:
        console.log(f'Make {type} output for: {s.station.place}', True)

        tg_gem = fix.ent(s.tg_gem, 'TG')
        tx_min = fix.ent(s.tx_min, 'TX')
        tg_min = fix.ent(s.tg_min, 'TG')
        tn_min = fix.ent(s.tn_min, 'TN')
        hellmann = fix.ent(s.sum_hellmann, 'hellmann')
        f_sum = fix.ent(s.frost_sum, 'frost_sum')
        ijnsen = fix.ent(s.ijnsen, 'ijnsen')
        sq_sum = fix.ent(s.sq_sum, 'SQ')
        rh_sum = fix.ent(s.rh_sum, 'RH')

        if type == 'html':
            period_txt = f'{utils.ymd_to_txt(s.date_s)} - {utils.ymd_to_txt(s.date_e)}'
            # TODO the extension html tables
            main += f'''
                <tr class="row-data">
                    <td title="{s.station.data_notification.lower()}">
                            {icon.copy_light(size='fa-xs')}
                    </td>
                    <td> <span class="val"> {s.station.place} </span> </td>
                    <td> <span class="val"> {s.station.province} </span> </td>
                    <td title="{period_txt}"> <span class="val"> {s.period} </span> </td>
                    <td> <span class="val"> {tg_gem} </span> </td>
                    <td>
                        <span class="val"> {hellmann} </span>
                        {vhtml.table_hellmann( s.days_tg_lt_0 )}
                    </td>
                    <td>
                        <span class="val"> {ijnsen} </span>
                    </td>
                    <td>
                        <span class="val"> {f_sum} </span>
                        {vhtml.table_frost_sum( s.frost_sum_data )}
                    </td>
                    <td>
                        <span class="val"> {tx_min} </span>
                        {vhtml.table_days( s.tx_min_sort, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {tg_min} </span>
                        {vhtml.table_days( s.tg_min_sort, 'TG' )}
                    </td>
                    <td>
                        <span class="val"> {tn_min} </span>
                        {vhtml.table_days( s.tn_min_sort, 'TN', 'TNH' )}
                    </td>
                    <td>
                        <span class="val"> {sq_sum} </span>
                        {vhtml.table_days( s.sq_sort, 'SQ' )}
                    </td>
                    <td>
                        <span class="val"> {rh_sum} </span>
                        {vhtml.table_days( s.rh_sort, 'RH' )}

                    </td>
                    <td>
                        <span class="val"> {np.size( s.days_tx_lt_0, axis=0 )} </span>
                        {vhtml.table_days_count( s.days_tx_lt_0, 'TX', 'TXH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size( s.days_tg_lt_0, axis=0 )} </span>
                        {vhtml.table_days_count( s.days_tg_lt_0, 'TG' )}
                    </td>
                    <td>
                        <span class="val"> {np.size( s.days_tn_lt_0, axis=0 )} </span>
                        {vhtml.table_days_count( s.days_tn_lt_0, 'TN', 'TNH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size( s.days_tn_lt__5, axis=0 )} </span>
                        {vhtml.table_days_count( s.days_tn_lt__5, 'TN', 'TNH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size( s.days_tn_lt__10, axis=0 )} </span>
                        {vhtml.table_days_count( s.days_tn_lt__10, 'TN', 'TNH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size( s.days_tn_lt__15, axis=0 )} </span>
                        {vhtml.table_days_count( s.days_tn_lt__15, 'TN', 'TNH' )}
                    </td>
                    <td>
                        <span class="val"> {np.size( s.days_tn_lt__20, axis=0 )} </span>
                        {vhtml.table_days_count( s.days_tn_lt__20, 'TN', 'TNH' )}
                    </td>
                </tr>
                '''

        elif type in ['txt', 'cmd']:
            main += f'{s.station.place:<23} '
            main += f'{s.station.province:17} '
            main += f'{s.station.period:18} '
            main += f'{tg_gem:7} '
            main += f'{hellmann:^8} '
            main += f'{tx_min:<7} '
            main += f'{tg_min:<7} '
            main += f'{tn_min:<7} '
            main += f'{np.size( s.days_tx_lt_0,   axis=0 ):^5} '
            main += f'{np.size( s.days_tg_lt_0,   axis=0 ):^5} '
            main += f'{np.size( s.days_tn_lt_0,   axis=0 ):^5} '
            main += f'{np.size( s.days_tn_lt__5,  axis=0 ):^6} '
            main += f'{np.size( s.days_tn_lt__10, axis=0 ):^6} '
            main += f'{np.size( s.days_tn_lt__15, axis=0 ):^6} '
            main += f'{np.size( s.days_tn_lt__20, axis=0 ):^6} \n'

    # Close of main, footer
    if type in ['txt', 'cmd']:
        footer += cfg.knmi_dayvalues_notification

    elif type == 'html':
        footer += f'''
            </tbody>
            <tfoot>
                <tr>
                    <td colspan="{colspan}">
                        {utils.now_created_notification()}
                    </td>
                </tr>
            </tfoot>
            </table>
            '''

    path_to_root = './../../'  # Path to html root
    console.log('\nWrite/print results... ', True)

    # Write to file or console
    output = f'{title}\n{main}\n{footer}'
    if type == 'cmd':
        console.log(output, True)

    elif type == 'html':
        page = vhtml.Template()
        page.title = table_title
        page.main = output
        page.strip = True
        page.path_to_root = path_to_root
        page.file_path = path
        # Styling
        page.css_files = [
            f'{path_to_root}winterstats/css/default.css',
            f'{path_to_root}static/css/table-statistics.css',
            f'{path_to_root}winterstats/css/winterstats.css'
        ]
        # Scripts
        page.script_files = [
            f'{path_to_root}winterstats/js/winterstats.js',
            f'{path_to_root}static/js/sort-col.js',
            f'{path_to_root}static/js/default.js'
        ]
        page.save()

    elif type == 'txt':
        fio.save(path, output)  # Schrijf naar bestand

    return path