@@ -324,19 +324,114 @@ def show_overview_table(
324324 print (df )
325325
326326
327+ def create_html_table (dest : Path ) -> None :
328+ from bokeh .io import output_file , save
329+ from bokeh .layouts import column
330+ from bokeh .models import (
331+ ColumnDataSource ,
332+ DataTable ,
333+ TableColumn ,
334+ Div ,
335+ StringFormatter ,
336+ NumberFormatter ,
337+ HTMLTemplateFormatter ,
338+ InlineStyleSheet ,
339+ )
340+
341+ dest .parent .mkdir (parents = True , exist_ok = True )
342+
343+ df = get_overview_df ()
344+
345+ df ["possible_discontinuities" ] = df ["possible_discontinuities" ].apply (
346+ lambda x : "✓" if x else ""
347+ )
348+
349+ source = ColumnDataSource (df )
350+
351+ def get_formatter (col : str ):
352+ """Get the appropriate formatter for the column."""
353+ if col not in df .columns :
354+ return HTMLTemplateFormatter (
355+ template = """
356+ <a href="https://github.com/Benchmarking-Initiative/Benchmark-Models-PEtab/tree/master/Benchmark-Models/<%= value %>"><%= value %></a>
357+ """
358+ )
359+ if pd .api .types .is_integer_dtype (df [col ].dtype ):
360+ return NumberFormatter (text_align = "right" )
361+ if col in ["reference_uris" , "sbml4humans_urls" ]:
362+ return HTMLTemplateFormatter (
363+ template = """
364+ <%
365+ const sanitizedValue = value.replace(/'/g, '"');
366+ const urls = JSON.parse(sanitizedValue);
367+ console.log('Parsed JSON:', urls);
368+ for (let i = 0; i < urls.length; i++) {
369+ %>
370+ <a href="<%= urls[i] %>" target="_blank"><%= urls[i] %></a>
371+ <% } %>
372+ """
373+ )
374+
375+ return StringFormatter ()
376+
377+ columns = [
378+ TableColumn (
379+ field = col ,
380+ title = markdown_columns .get (col , col ),
381+ formatter = get_formatter (col ),
382+ width = len (col ),
383+ )
384+ for col in df .reset_index ().columns
385+ ]
386+
387+ css = InlineStyleSheet (
388+ css = """
389+ .slick-header-column {
390+ background-color: #f4f4f4;
391+ font-weight: bold;
392+ }
393+ """
394+ )
395+
396+ data_table = DataTable (
397+ source = source ,
398+ columns = columns ,
399+ sortable = True ,
400+ sizing_mode = "stretch_both" ,
401+ )
402+ data_table .stylesheets .append (css )
403+
404+ heading = Div (text = "<h1>Benchmark Problems</h1>" )
405+
406+ layout = column (heading , data_table , sizing_mode = "stretch_both" )
407+ output_file (dest , title = "Benchmark Problems" )
408+ save (layout )
409+
410+
327411def main ():
328412 parser = argparse .ArgumentParser (
329413 description = "Show overview table for benchmark PEtab problems"
330414 )
331- parser .add_argument (
415+ group1 = parser .add_mutually_exclusive_group ()
416+ group1 .add_argument (
332417 "--markdown" , action = "store_true" , help = "Output in markdown format"
333418 )
334- parser .add_argument (
419+ group1 .add_argument (
335420 "--update" ,
336421 action = "store_true" ,
337422 help = "Update the README.md file with the overview table" ,
338423 )
339424
425+ group2 = parser .add_mutually_exclusive_group ()
426+ group2 .add_argument (
427+ "--html-file" , help = "Output the overview table to an HTML file"
428+ )
429+
340430 args = parser .parse_args ()
341431
342- show_overview_table (markdown = args .markdown , update_readme = args .update )
432+ if args .html_file :
433+ create_html_table (dest = Path (args .html_file ))
434+ else :
435+ show_overview_table (
436+ markdown = args .markdown , update_readme = args .update , html = args .html
437+ )
0 commit comments