簡易HTMLの作成ライブラリ

簡易HTMLによる実験データの整理など

  • データをHTMLで見やすくしたい.

  • csv や json、png などの形式のデータを HTMLに変換する.

使用方法

呼び出し

import nkUtilities.generate__html as ght
ght.generate__html( html_config="dat/html_config.json" )

入力コンフィグファイル

{

    "settings":{
	
	"title"      : "test page", 
	"cssFile"    : "dat/style.css",
	"paramsFile" : "dat/ri_prod.json",
	"htmlFile"   : "html/output.html",
	"csvFile"    : "dat/sample.csv", 
	
    },
    
    "images":{
	
	"image1":{
	    filepath : "png/dice.jpg",
	    width    : "100px",
	},
	
	"image2":{
	    filepath : "png/dice.jpg",
	    width    : "400px",
	},
	
    },
    
}
  • paramsFile はjson ファイル形式

コード

#!/usr/bin/env python3
import os, sys, json5, argparse, shutil
import nkUtilities.json__formulaParser as jso
import pandas as pd
# ========================================================= #
# ===  translate__json2html                             === #
# ========================================================= #

def translate__json2html( data ):

    # ------------------------------------------------- #
    # --- [1] recursive translation                 --- #
    # ------------------------------------------------- #
    if   isinstance( data, type(None) ):           #  -- None -- #
        return( '<div class="bool-true">None</div>\n' )
    
    elif isinstance( data, bool ):                 #  -- bool -- #
        sval = str(data)
        return( '<div class="bool-{0}">{1}</div>\n'.format( sval.lower(), sval ) )
        
    elif isinstance( data, str  ):                 #  -- str  -- #
        if ( len(data) == 0):
            return( '<span class="string empty">(Empty Text)</span>\n' )
        else:
            return( f'<span class="string">{data}</span>\n' )
        
    elif isinstance(data, (int, float)):
        # INT or FLOAT
        if isinstance(data, int):
            class_name = "int number"
        else:
            class_name = "float number"
        return f'<span class="{class_name}">{data}</span>\n'
    elif isinstance(data, list):
        # ARRAY
        if len(data) > 0:
            html = '<table class="array">\n'
            for i, item in enumerate(data):
                html += '<tr>\n'
                html += '<td class="value array-value">\n'
                html += translate__json2html( data=item )
                html += '</td></tr>\n'
            html += '</table>\n'
            return html
        else:
            return '<span class="array empty">(Empty List)</span>\n'
    elif isinstance( data, dict ):
        # OBJECT
        html = '<table class="object">\n'
        for key, value in data.items():
            html += '<tr>\n'
            html += f'<th class="key object-key">{key}</th>\n'
            html += '<td class="value object-value">\n'
            html += translate__json2html( data=value )
            html += '</td></tr>\n'
        html += '</table>\n'
        return html
    elif callable(data):
        # FUNCTION
        return f'<span class="function">{data}</span>\n'
    else:
        # UNKNOWN
        return f'<span class="unknown">{data}</span>\n'


# ========================================================= #
# ===  generate__html                                   === #
# ========================================================= #

def generate__html( html_lines=[],  html_config=None, silent=False ):

    
    if ( html_config is None ): sys.exit( "[generate__html.py] html_config == ???" )
    title, paramsFile   = None, None
    cssFile, htmlFile   = None, None
    config              = jso.json__formulaParser( inpFile=html_config )
    settings, images    = config["settings"], config["images"]
    if ( "cssFile"    in settings ): cssFile    = settings[ "cssFile"    ]
    if ( "title"      in settings ): title      = settings[ "title"      ]
    if ( "paramsFile" in settings ): paramsFile = settings[ "paramsFile" ]
    if ( "htmlFile"   in settings ): htmlFile   = settings[ "htmlFile"   ]
    if ( "csvFile"    in settings ): csvFile    = settings[ "csvFile"    ]

    # ------------------------------------------------- #
    # --- [1] html header part                      --- #
    # ------------------------------------------------- #
    html_lines      += [ "<html>", "<head>" ]
    if ( title   ):
        html_lines  += [ f"<title>{title}</title>" ]
    if ( cssFile ):
        if ( htmlFile ):
            css_filepath = os.path.basename( cssFile )
            out_dirpath  = os.path.dirname ( htmlFile )
            css_copypath = os.path.join( out_dirpath, css_filepath )
            shutil.copy( cssFile, css_copypath )
        html_lines  += [ f'<link rel="stylesheet" type="text/css" href="{css_filepath}"/>\n' ] 
    html_lines      += [ "</head>", "<body>" ]
   
    # ------------------------------------------------- #
    # --- [2] html body part                        --- #
    # ------------------------------------------------- #
    if ( title ):
        html_lines += [ f'<h1>{title}</h1>\n' ]
    if ( paramsFile ):
        if ( os.path.exists( paramsFile ) ):
            data  = jso.json__formulaParser( inpFile=paramsFile )
        else:
            print( "[generate__html.py] cannot find paramsFile... {} ".format( paramsFile ) )
            sys.exit()
        translation  = translate__json2html( data )
        html_lines  += [ translation ]

    # ------------------------------------------------- #
    # --- [3] html image file                       --- #
    # ------------------------------------------------- #
    if ( csvFile ):
        csvData     = pd.read_csv( csvFile )
        csvData     = csvData.set_index( csvData.columns[0] )
        html_lines += [ csvData.to_html( classes='table_design', index_names=False ) ]

    # ------------------------------------------------- #
    # --- [4] html image file                       --- #
    # ------------------------------------------------- #
    imgtag = '<img src="../{0}" width="{1}">'
    for key,obj in images.items():
        command     = imgtag.format( obj["filepath"], obj["width"] )
        if ( not( "line_break" in obj  ) ): obj["line_break"] = True
        if ( obj["line_break"] is True   ): command = f"<p> {command} </p>"
        html_lines += [ command ]
        
    # ------------------------------------------------- #
    # --- [5] html closing part / save html file    --- #
    # ------------------------------------------------- #
    html_lines  += [ "</body>", "</html>" ]
    html_strings = "\n".join( html_lines )

    if ( htmlFile ):
        with open( htmlFile, "w" ) as f:
            f.write( html_strings )
        if not( silent ):
            print( "[generate__html.py] output file :: {}".format( htmlFile ) )
    return( html_strings )
            
    
# ========================================================= #
# ===   Execution of Pragram                            === #
# ========================================================= #

if ( __name__=="__main__" ):

    default_html_config = "dat/html_config.json"
    
    # ------------------------------------------------- #
    # --- [1] arguments                             --- #
    # ------------------------------------------------- #
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument( "--html_config", help="system config file for html." )
    parser.add_argument( "-s","--silent", help="no display", \
                         default=False, action="store_true" )
    args   = parser.parse_args()

    if args.html_config:
        html_config = args.html_config
    else:
        html_config = default_html_config

    # ------------------------------------------------- #
    # --- [2] call arguments                        --- #
    # ------------------------------------------------- #
    generate__html( html_config=html_config, silent=args.silent )
    

実行結果

<html>
<head>
<title>test page</title>
<link rel="stylesheet" type="text/css" href="style.css"/>

</head>
<body>
<h1>test page</h1>

<table class="object">
<tr>
<th class="key object-key">results.summaryFile</th>
<td class="value object-value">
<span class="string">dat/summary.dat</span>
</td></tr>
<tr>
<th class="key object-key">results.time.unit</th>
<td class="value object-value">
<span class="string">d</span>
</td></tr>
<tr>
<th class="key object-key">results.yieldFile</th>
<td class="value object-value">
<span class="string">dat/yield.dat</span>
</td></tr>
<tr>
<th class="key object-key">target.g/cm3</th>
<td class="value object-value">
<span class="float number">19.3</span>
</td></tr>
<tr>
<th class="key object-key">target.g/mol</th>
<td class="value object-value">
<span class="float number">197.0</span>
</td></tr>
<tr>
<th class="key object-key">target.mass.mg</th>
<td class="value object-value">
<span class="float number">4.75</span>
</td></tr>
<tr>
<th class="key object-key">target.activity.Bq</th>
<td class="value object-value">
<div class="bool-true">None</div>
</td></tr>
<tr>
<th class="key object-key">target.halflife</th>
<td class="value object-value">
<table class="object">
<tr>
<th class="key object-key">value</th>
<td class="value object-value">
<div class="bool-true">None</div>
</td></tr>
<tr>
<th class="key object-key">unit</th>
<td class="value object-value">
<span class="string">y</span>
</td></tr>
</table>
</td></tr>
<tr>
<th class="key object-key">product.halflife</th>
<td class="value object-value">
<table class="object">
<tr>
<th class="key object-key">value</th>
<td class="value object-value">
<span class="float number">6.16</span>
</td></tr>
<tr>
<th class="key object-key">unit</th>
<td class="value object-value">
<span class="string">d</span>
</td></tr>
</table>
</td></tr>
<tr>
<th class="key object-key">decayed.halflife</th>
<td class="value object-value">
<table class="object">
<tr>
<th class="key object-key">value</th>
<td class="value object-value">
<div class="bool-true">None</div>
</td></tr>
<tr>
<th class="key object-key">unit</th>
<td class="value object-value">
<span class="string">d</span>
</td></tr>
</table>
</td></tr>
<tr>
<th class="key object-key">target.thick.type</th>
<td class="value object-value">
<span class="string">fluence-mass</span>
</td></tr>
<tr>
<th class="key object-key">target.thick.direct.mm</th>
<td class="value object-value">
<span class="float number">1.0</span>
</td></tr>
<tr>
<th class="key object-key">target.area.type</th>
<td class="value object-value">
<span class="string">disk</span>
</td></tr>
<tr>
<th class="key object-key">target.area.direct.cm2</th>
<td class="value object-value">
<span class="float number">0.0707</span>
</td></tr>
<tr>
<th class="key object-key">target.area.diameter.mm</th>
<td class="value object-value">
<span class="float number">3.0</span>
</td></tr>
<tr>
<th class="key object-key">integral.method</th>
<td class="value object-value">
<span class="string">simpson</span>
</td></tr>
<tr>
<th class="key object-key">integral.EAxis.min</th>
<td class="value object-value">
<span class="float number">0.0</span>
</td></tr>
<tr>
<th class="key object-key">integral.EAxis.max</th>
<td class="value object-value">
<span class="float number">50.0</span>
</td></tr>
<tr>
<th class="key object-key">integral.EAxis.num</th>
<td class="value object-value">
<span class="int number">501</span>
</td></tr>
<tr>
<th class="key object-key">photon.filetype</th>
<td class="value object-value">
<span class="string">phits-out</span>
</td></tr>
<tr>
<th class="key object-key">photon.filename</th>
<td class="value object-value">
<span class="string">out/fluence_energy.dat</span>
</td></tr>
<tr>
<th class="key object-key">photon.bin2point.convert</th>
<td class="value object-value">
<span class="string">edge</span>
</td></tr>
<tr>
<th class="key object-key">photon.fit.method</th>
<td class="value object-value">
<span class="string">linear</span>
</td></tr>
<tr>
<th class="key object-key">photon.fit.p0</th>
<td class="value object-value">
<div class="bool-true">None</div>
</td></tr>
<tr>
<th class="key object-key">photon.fit.Eth</th>
<td class="value object-value">
<span class="float number">6.4</span>
</td></tr>
<tr>
<th class="key object-key">photon.beam.current.sim</th>
<td class="value object-value">
<span class="float number">100.0</span>
</td></tr>
<tr>
<th class="key object-key">photon.beam.current.use</th>
<td class="value object-value">
<span class="float number">6.2</span>
</td></tr>
<tr>
<th class="key object-key">photon.beam.duration</th>
<td class="value object-value">
<span class="float number">0.1667</span>
</td></tr>
<tr>
<th class="key object-key">xsection.filename</th>
<td class="value object-value">
<span class="string">dat/xs__JENDL_Au197_gn_Au196.dat</span>
</td></tr>
<tr>
<th class="key object-key">xsection.database</th>
<td class="value object-value">
<span class="string">JENDL</span>
</td></tr>
<tr>
<th class="key object-key">xsection.fit.Eth</th>
<td class="value object-value">
<span class="float number">8.07</span>
</td></tr>
<tr>
<th class="key object-key">xsection.fit.method</th>
<td class="value object-value">
<span class="string">linear</span>
</td></tr>
<tr>
<th class="key object-key">xsection.fit.p0</th>
<td class="value object-value">
<div class="bool-true">None</div>
</td></tr>
<tr>
<th class="key object-key">plot.filename</th>
<td class="value object-value">
<span class="string">png/dYield__RIproduction.png</span>
</td></tr>
<tr>
<th class="key object-key">plot.xRange</th>
<td class="value object-value">
<table class="array">
<tr>
<td class="value array-value">
<span class="float number">0.0</span>
</td></tr>
<tr>
<td class="value array-value">
<span class="float number">20.0</span>
</td></tr>
<tr>
<td class="value array-value">
<span class="int number">11</span>
</td></tr>
</table>
</td></tr>
<tr>
<th class="key object-key">plot.yRange</th>
<td class="value object-value">
<table class="array">
<tr>
<td class="value array-value">
<span class="float number">0.0</span>
</td></tr>
<tr>
<td class="value array-value">
<span class="float number">10.0</span>
</td></tr>
<tr>
<td class="value array-value">
<span class="int number">11</span>
</td></tr>
</table>
</td></tr>
<tr>
<th class="key object-key">plot.xsection.norm</th>
<td class="value object-value">
<span class="float number">100.0</span>
</td></tr>
<tr>
<th class="key object-key">plot.photon.norm</th>
<td class="value object-value">
<span class="float number">10000.0</span>
</td></tr>
<tr>
<th class="key object-key">plot.dYield.norm</th>
<td class="value object-value">
<span class="float number">10000.0</span>
</td></tr>
<tr>
<th class="key object-key">plot.norm.auto</th>
<td class="value object-value">
<div class="bool-true">True</div>
</td></tr>
</table>

<table border="1" class="dataframe table_design">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>math</th>
      <th>english</th>
      <th>physics</th>
      <th>geology</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>tom</th>
      <td>90</td>
      <td>100</td>
      <td>80</td>
      <td>95</td>
    </tr>
    <tr>
      <th>bob</th>
      <td>80</td>
      <td>70</td>
      <td>60</td>
      <td>98</td>
    </tr>
    <tr>
      <th>jessy</th>
      <td>50</td>
      <td>50</td>
      <td>60</td>
      <td>80</td>
    </tr>
  </tbody>
</table>
<p> <img src="../png/dice.jpg" width="100px"> </p>
<p> <img src="../png/dice.jpg" width="400px"> </p>
</body>
</html>