|
15 | 15 | import sympy as sp |
16 | 16 | from sympy.core.relational import Relational |
17 | 17 |
|
| 18 | +REPO_URL = "https://github.com/Benchmarking-Initiative/Benchmark-Models-PEtab/" |
18 | 19 |
|
19 | 20 | readme_md = Path(__file__).resolve().parent.parent / "README.md" |
20 | 21 |
|
@@ -324,19 +325,130 @@ def show_overview_table( |
324 | 325 | print(df) |
325 | 326 |
|
326 | 327 |
|
| 328 | +def create_html_table(dest: Path) -> None: |
| 329 | + """Create HTML table with stats for all benchmark PEtab problems. |
| 330 | +
|
| 331 | + :param dest: Path to the output HTML file. |
| 332 | + """ |
| 333 | + from bokeh.io import output_file, save |
| 334 | + from bokeh.layouts import column |
| 335 | + from bokeh.models import ( |
| 336 | + ColumnDataSource, |
| 337 | + DataTable, |
| 338 | + TableColumn, |
| 339 | + Div, |
| 340 | + StringFormatter, |
| 341 | + NumberFormatter, |
| 342 | + HTMLTemplateFormatter, |
| 343 | + InlineStyleSheet, |
| 344 | + ) |
| 345 | + |
| 346 | + dest.parent.mkdir(parents=True, exist_ok=True) |
| 347 | + |
| 348 | + # get the overview dataframe and prettify it |
| 349 | + df = get_overview_df() |
| 350 | + df["possible_discontinuities"] = df["possible_discontinuities"].apply( |
| 351 | + lambda x: "✓" if x else "" |
| 352 | + ) |
| 353 | + df.fillna({"objective_prior_distributions": ""}, inplace=True) |
| 354 | + |
| 355 | + def get_formatter(col: str): |
| 356 | + """Get the appropriate formatter for the column.""" |
| 357 | + if col not in df.columns: |
| 358 | + # index column |
| 359 | + return HTMLTemplateFormatter( |
| 360 | + template=f""" |
| 361 | + <a href="{REPO_URL}tree/master/Benchmark-Models/<%= value %>"><%= value %></a> |
| 362 | + """ |
| 363 | + ) |
| 364 | + if pd.api.types.is_integer_dtype(df[col].dtype): |
| 365 | + return NumberFormatter(text_align="right") |
| 366 | + if col in ["reference_uris", "sbml4humans_urls"]: |
| 367 | + return HTMLTemplateFormatter( |
| 368 | + template=""" |
| 369 | + <% |
| 370 | + if (Array.isArray(value)) { |
| 371 | + urls = value; |
| 372 | + } else { |
| 373 | + const sanitizedValue = value.replace(/'/g, '"'); |
| 374 | + const urls = JSON.parse(sanitizedValue); |
| 375 | + console.log('Parsed JSON:', urls); |
| 376 | + } |
| 377 | + for (let i = 0; i < urls.length; i++) { |
| 378 | + %> |
| 379 | + <a href="<%= urls[i] %>" target="_blank"><%= urls[i] %></a> |
| 380 | + <% } %> |
| 381 | + """ |
| 382 | + ) |
| 383 | + |
| 384 | + return StringFormatter() |
| 385 | + |
| 386 | + columns = [ |
| 387 | + TableColumn( |
| 388 | + field=col, |
| 389 | + title=markdown_columns.get(col, col), |
| 390 | + formatter=get_formatter(col), |
| 391 | + width=len(col), |
| 392 | + ) |
| 393 | + for col in df.reset_index().columns |
| 394 | + ] |
| 395 | + |
| 396 | + source = ColumnDataSource(df) |
| 397 | + |
| 398 | + css = InlineStyleSheet( |
| 399 | + css=""" |
| 400 | + .slick-header-column { |
| 401 | + background-color: #f4f4f4; |
| 402 | + font-weight: bold; |
| 403 | + } |
| 404 | + """ |
| 405 | + ) |
| 406 | + |
| 407 | + data_table = DataTable( |
| 408 | + source=source, |
| 409 | + columns=columns, |
| 410 | + sortable=True, |
| 411 | + sizing_mode="stretch_both", |
| 412 | + ) |
| 413 | + data_table.stylesheets.append(css) |
| 414 | + |
| 415 | + heading = Div(text="<h1>Benchmark Problems</h1>") |
| 416 | + preamble = Div( |
| 417 | + text=f""" |
| 418 | + <p> |
| 419 | + This table provides an overview of the benchmark problems |
| 420 | + available in the <a href="{REPO_URL}">Benchmark-Models-PEtab</a> |
| 421 | + repository. |
| 422 | + </p> |
| 423 | + """ |
| 424 | + ) |
| 425 | + layout = column(heading, preamble, data_table, sizing_mode="stretch_both") |
| 426 | + output_file(dest, title="Benchmark Problems") |
| 427 | + save(layout) |
| 428 | + |
| 429 | + |
327 | 430 | def main(): |
328 | 431 | parser = argparse.ArgumentParser( |
329 | 432 | description="Show overview table for benchmark PEtab problems" |
330 | 433 | ) |
331 | | - parser.add_argument( |
| 434 | + group1 = parser.add_mutually_exclusive_group() |
| 435 | + group1.add_argument( |
332 | 436 | "--markdown", action="store_true", help="Output in markdown format" |
333 | 437 | ) |
334 | | - parser.add_argument( |
| 438 | + group1.add_argument( |
335 | 439 | "--update", |
336 | 440 | action="store_true", |
337 | 441 | help="Update the README.md file with the overview table", |
338 | 442 | ) |
339 | 443 |
|
| 444 | + group2 = parser.add_mutually_exclusive_group() |
| 445 | + group2.add_argument( |
| 446 | + "--html-file", help="Output the overview table to an HTML file" |
| 447 | + ) |
| 448 | + |
340 | 449 | args = parser.parse_args() |
341 | 450 |
|
342 | | - show_overview_table(markdown=args.markdown, update_readme=args.update) |
| 451 | + if args.html_file: |
| 452 | + create_html_table(dest=Path(args.html_file)) |
| 453 | + else: |
| 454 | + show_overview_table(markdown=args.markdown, update_readme=args.update) |
0 commit comments