1313
1414class Table :
1515 """
16- Initializes a Table object. Tables can include image columns using the Image class .
16+ Initializes a Table object. Tables can be used to log tabular data including images, numbers, and text .
1717
1818 Args:
1919 columns (`list[str]`, *optional*):
2020 Names of the columns in the table. Optional if `data` is provided. Not
2121 expected if `dataframe` is provided. Currently ignored.
2222 data (`list[list[Any]]`, *optional*):
23- 2D row-oriented array of values.
23+ 2D row-oriented array of values. Each value can be: a number, a string (treated as Markdown and truncated if too long),
24+ or a `Trackio.Image` or list of `Trackio.Image` objects.
2425 dataframe (`pandas.`DataFrame``, *optional*):
2526 DataFrame object used to create the table. When set, `data` and `columns`
2627 arguments are ignored.
@@ -54,10 +55,20 @@ def __init__(
5455 self .data = dataframe
5556
5657 def _has_media_objects (self , dataframe : DataFrame ) -> bool :
57- """Check if dataframe contains any TrackioMedia objects."""
58+ """Check if dataframe contains any TrackioMedia objects or lists of TrackioMedia objects ."""
5859 for col in dataframe .columns :
5960 if dataframe [col ].apply (lambda x : isinstance (x , TrackioMedia )).any ():
6061 return True
62+ if (
63+ dataframe [col ]
64+ .apply (
65+ lambda x : isinstance (x , list )
66+ and len (x ) > 0
67+ and isinstance (x [0 ], TrackioMedia )
68+ )
69+ .any ()
70+ ):
71+ return True
6172 return False
6273
6374 def _process_data (self , project : str , run : str , step : int = 0 ):
@@ -73,6 +84,13 @@ def _process_data(self, project: str, run: str, step: int = 0):
7384 if isinstance (value , TrackioMedia ):
7485 value ._save (project , run , step )
7586 processed_df .at [idx , col ] = value ._to_dict ()
87+ if (
88+ isinstance (value , list )
89+ and len (value ) > 0
90+ and isinstance (value [0 ], TrackioMedia )
91+ ):
92+ [v ._save (project , run , step ) for v in value ]
93+ processed_df .at [idx , col ] = [v ._to_dict () for v in value ]
7694
7795 return processed_df .to_dict (orient = "records" )
7896
@@ -86,19 +104,33 @@ def to_display_format(table_data: list[dict]) -> list[dict]:
86104 table_data: List of dictionaries representing table rows (from stored _value)
87105
88106 Returns:
89- Table data with images converted to markdown syntax
107+ Table data with images converted to markdown syntax and long text truncated.
90108 """
91109 truncate_length = int (os .getenv ("TRACKIO_TABLE_TRUNCATE_LENGTH" , "250" ))
110+
111+ def convert_image_to_markdown (image_data : dict ) -> str :
112+ relative_path = image_data .get ("file_path" , "" )
113+ caption = image_data .get ("caption" , "" )
114+ absolute_path = MEDIA_DIR / relative_path
115+ return f'<img src="/gradio_api/file={ absolute_path } " alt="{ caption } " />'
116+
92117 processed_data = []
93118 for row in table_data :
94119 processed_row = {}
95120 for key , value in row .items ():
96121 if isinstance (value , dict ) and value .get ("_type" ) == "trackio.image" :
97- relative_path = value .get ("file_path" , "" )
98- caption = value .get ("caption" , "" )
99- absolute_path = MEDIA_DIR / relative_path
122+ processed_row [key ] = convert_image_to_markdown (value )
123+ elif (
124+ isinstance (value , list )
125+ and len (value ) > 0
126+ and isinstance (value [0 ], dict )
127+ and value [0 ].get ("_type" ) == "trackio.image"
128+ ):
129+ # This assumes that if the first item is an image, all items are images. Ok for now since we don't support mixed types in a single cell.
100130 processed_row [key ] = (
101- f""
131+ '<div style="display: flex; gap: 10px;">'
132+ + "" .join ([convert_image_to_markdown (item ) for item in value ])
133+ + "</div>"
102134 )
103135 elif isinstance (value , str ) and len (value ) > truncate_length :
104136 truncated = value [:truncate_length ]
0 commit comments