kartikmandar commited on
Commit
8dfd384
·
1 Parent(s): 44f8493

eventlist.read done correctly

Browse files
modules/DataLoading/DataIngestion.py CHANGED
@@ -255,15 +255,9 @@ def read_event_data(
255
  if format_checkbox.value:
256
  formats = ["ogip" for _ in range(len(file_paths))]
257
 
258
- # Parse optional RMF file from FileDropper
259
- rmf_file = None
260
  if rmf_file_dropper.value:
261
- # Retrieve the uploaded RMF file
262
- rmf_file_name, rmf_file_bytes = list(rmf_file_dropper.value.items())[0]
263
- rmf_file_path = os.path.join(loaded_data_path, rmf_file_name)
264
- with open(rmf_file_path, "wb") as f:
265
- f.write(rmf_file_bytes)
266
- rmf_file = rmf_file_path
267
 
268
  # Parse additional columns
269
  additional_columns = (
@@ -282,8 +276,12 @@ def read_event_data(
282
  )
283
  ]
284
  return
285
-
286
- event_list = EventList.read(file_path, fmt=file_format, rmf_file=rmf_file, additional_columns=additional_columns)
 
 
 
 
287
  loaded_event_data.append((file_name, event_list))
288
  loaded_files.append(
289
  f"File '{file_path}' loaded successfully as '{file_name}' with format '{file_format}'."
@@ -540,7 +538,19 @@ def preview_loaded_files(
540
  time_data = f"Times (first {time_limit}): {event_list.time[:time_limit]}"
541
  mjdref = f"MJDREF: {event_list.mjdref}"
542
  gti = f"GTI: {event_list.gti}"
543
- preview_data.append(f"Event List - {file_name}:\n{time_data}\n{mjdref}\n{gti}\n")
 
 
 
 
 
 
 
 
 
 
 
 
544
  except Exception as e:
545
  warning_handler.warn(str(e), category=RuntimeWarning)
546
 
@@ -864,19 +874,19 @@ def create_loading_tab(output_box_container, warning_box_container, warning_hand
864
  format_checkbox = pn.widgets.Checkbox(
865
  name="Use default format (\"ogip\" for reading, \"hdf5\" for writing/saving)", value=False
866
  )
867
- load_button = pn.widgets.Button(name="Load Event Data", button_type="primary")
868
- save_button = pn.widgets.Button(name="Save Loaded Data", button_type="success")
869
  delete_button = pn.widgets.Button(
870
  name="Delete Selected Files", button_type="danger"
871
  )
872
  preview_button = pn.widgets.Button(
873
- name="Preview Loaded Files", button_type="default"
874
  )
875
- clear_button = pn.widgets.Button(name="Clear Loaded Files", button_type="warning")
876
 
877
  tooltip_format = pn.widgets.TooltipIcon(
878
  value=Tooltip(
879
- content="""For HEASoft-supported missions, use 'ogip'. Using 'fits' directly might cause issues with Astropy tables. default = ogip (for reading), hdf5 (for saving)""",
880
  position="bottom",
881
  )
882
  )
@@ -890,25 +900,25 @@ def create_loading_tab(output_box_container, warning_box_container, warning_hand
890
 
891
  tooltip_rmf = pn.widgets.TooltipIcon(
892
  value=Tooltip(
893
- content="""for energy calibration""",
894
  position="bottom",
895
  )
896
  )
897
 
898
  tooltip_additional_columns = pn.widgets.TooltipIcon(
899
  value=Tooltip(
900
- content="""further keyword arguments to be passed to OGIP/HEASOFT format""",
901
  position="bottom",
902
  )
903
  )
904
 
905
  # FileDropper for RMF file
906
  rmf_file_dropper = pn.widgets.FileDropper(
907
- accepted_filetypes=[".rmf", ".fits"], # Accept RMF files or compatible FITS files
908
  multiple=False, # Only allow a single file
909
- name="Upload RMF File (optional)",
910
  max_file_size="1000MB", # Limit file size
911
- layout="integrated", # Layout style
912
  )
913
 
914
  additional_columns_input = pn.widgets.TextInput(
@@ -994,14 +1004,15 @@ def create_loading_tab(output_box_container, warning_box_container, warning_hand
994
  clear_button.on_click(on_clear_click)
995
 
996
  first_column = pn.Column(
997
- pn.Row(pn.pane.Markdown("<h2> Read an EventList object from File</h2>"),pn.widgets.TooltipIcon(value=Tooltip(content="Supported Formats: pickle, hea or ogip, any other astropy.table.Table", position="bottom"))),
998
  file_selector,
999
  pn.Row(filename_input, tooltip_file),
1000
  pn.Row(format_input, tooltip_format),
1001
  format_checkbox,
1002
  pn.Row(rmf_file_dropper, tooltip_rmf),
1003
  pn.Row(additional_columns_input, tooltip_additional_columns),
1004
- pn.Row(load_button, save_button, delete_button, preview_button, clear_button),
 
1005
  pn.pane.Markdown("<br/>"),
1006
  width_policy="min",
1007
  )
@@ -1213,14 +1224,215 @@ def create_loadingdata_help_area():
1213
 
1214
  Returns:
1215
  HelpBox: An instance of HelpBox with the help content.
1216
-
1217
- Example:
1218
- >>> help_area = create_loadingdata_help_area()
1219
- >>> isinstance(help_area, HelpBox)
1220
- True
1221
  """
1222
- help_content = LOADING_DATA_HELP_BOX_STRING
1223
- return HelpBox(help_content=help_content, title="Help Section")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1224
 
1225
 
1226
  def create_loadingdata_plots_area():
 
255
  if format_checkbox.value:
256
  formats = ["ogip" for _ in range(len(file_paths))]
257
 
258
+ # Retrieve the RMF file from FileDropper (if any)
 
259
  if rmf_file_dropper.value:
260
+ rmf_file = rmf_file_dropper.value
 
 
 
 
 
261
 
262
  # Parse additional columns
263
  additional_columns = (
 
276
  )
277
  ]
278
  return
279
+ # Handle rmf_file separately for 'hea' or 'ogip' formats
280
+ if file_format in ("hea", "ogip"):
281
+ event_list = EventList.read(file_path, fmt=file_format, additional_columns=additional_columns)
282
+ else:
283
+ # Directly pass rmf_file content for other formats
284
+ event_list = EventList.read(file_path, fmt=file_format, rmf_file=rmf_file,additional_columns=additional_columns)
285
  loaded_event_data.append((file_name, event_list))
286
  loaded_files.append(
287
  f"File '{file_path}' loaded successfully as '{file_name}' with format '{file_format}'."
 
538
  time_data = f"Times (first {time_limit}): {event_list.time[:time_limit]}"
539
  mjdref = f"MJDREF: {event_list.mjdref}"
540
  gti = f"GTI: {event_list.gti}"
541
+ pi_data = (
542
+ f"PI (first {time_limit}): {event_list.pi[:time_limit]}"
543
+ if event_list.pi is not None
544
+ else "PI: Not available"
545
+ )
546
+ energy_data = (
547
+ f"Energy (first {time_limit}): {event_list.energy[:time_limit]}"
548
+ if event_list.energy is not None
549
+ else "Energy: Not available"
550
+ )
551
+ preview_data.append(
552
+ f"Event List - {file_name}:\n{time_data}\n{mjdref}\n{gti}\n{pi_data}\n{energy_data}\n"
553
+ )
554
  except Exception as e:
555
  warning_handler.warn(str(e), category=RuntimeWarning)
556
 
 
874
  format_checkbox = pn.widgets.Checkbox(
875
  name="Use default format (\"ogip\" for reading, \"hdf5\" for writing/saving)", value=False
876
  )
877
+ load_button = pn.widgets.Button(name="Read as EventLists", button_type="primary")
878
+ save_button = pn.widgets.Button(name="Save loaded EventLists", button_type="success")
879
  delete_button = pn.widgets.Button(
880
  name="Delete Selected Files", button_type="danger"
881
  )
882
  preview_button = pn.widgets.Button(
883
+ name="Preview loaded EventLists", button_type="default"
884
  )
885
+ clear_button = pn.widgets.Button(name="Clear Loaded EventLists", button_type="warning")
886
 
887
  tooltip_format = pn.widgets.TooltipIcon(
888
  value=Tooltip(
889
+ content="""For HEASoft-supported missions, use 'ogip'. Using 'fits' directly might cause issues with Astropy tables.""",
890
  position="bottom",
891
  )
892
  )
 
900
 
901
  tooltip_rmf = pn.widgets.TooltipIcon(
902
  value=Tooltip(
903
+ content="""Calibrates PI(Pulse invariant) values to physical energy.""",
904
  position="bottom",
905
  )
906
  )
907
 
908
  tooltip_additional_columns = pn.widgets.TooltipIcon(
909
  value=Tooltip(
910
+ content="""Any further keyword arguments to be passed for reading in event lists in OGIP/HEASOFT format""",
911
  position="bottom",
912
  )
913
  )
914
 
915
  # FileDropper for RMF file
916
  rmf_file_dropper = pn.widgets.FileDropper(
917
+ # accepted_filetypes=['.rmf', '.fits'], # Accept RMF files or compatible FITS files
918
  multiple=False, # Only allow a single file
919
+ name="Upload RMF(Response Matrix File) File (optional)",
920
  max_file_size="1000MB", # Limit file size
921
+ layout="compact", # Layout style
922
  )
923
 
924
  additional_columns_input = pn.widgets.TextInput(
 
1004
  clear_button.on_click(on_clear_click)
1005
 
1006
  first_column = pn.Column(
1007
+ pn.Row(pn.pane.Markdown("<h2> Read an EventList object from File</h2>"),pn.widgets.TooltipIcon(value=Tooltip(content="Supported Formats: pickle, hea or ogip, any other astropy.table.Table(ascii.ecsv, hdf5, etc.)", position="bottom"))),
1008
  file_selector,
1009
  pn.Row(filename_input, tooltip_file),
1010
  pn.Row(format_input, tooltip_format),
1011
  format_checkbox,
1012
  pn.Row(rmf_file_dropper, tooltip_rmf),
1013
  pn.Row(additional_columns_input, tooltip_additional_columns),
1014
+ pn.Row(load_button, save_button, delete_button),
1015
+ pn.Row(preview_button, clear_button),
1016
  pn.pane.Markdown("<br/>"),
1017
  width_policy="min",
1018
  )
 
1224
 
1225
  Returns:
1226
  HelpBox: An instance of HelpBox with the help content.
 
 
 
 
 
1227
  """
1228
+
1229
+ # Content for "Introduction to Event Lists"
1230
+ intro_content = """
1231
+ ## Introduction to Event Lists
1232
+
1233
+ ### What are Event Lists?
1234
+
1235
+ In X-ray astronomy, an **Event List** represents a record of individual photon detection events as observed by a telescope. Each event corresponds to the detection of a photon and includes attributes like:
1236
+ - **Time of Arrival (TOA)**: The exact time when the photon was detected.
1237
+ - **Photon Energy**: Derived from the pulse height or energy channel recorded.
1238
+ - **Good Time Intervals (GTIs)**: Periods during which the instrument was actively recording valid data.
1239
+ - **Pulse Invariant (PI) Channel**: A standardized representation of photon energy.
1240
+
1241
+ Event Lists are typically the starting point for data analysis in high-energy astrophysics. They provide unbinned, high-precision information about individual photon arrivals, enabling various scientific analyses such as timing, spectral, and correlation studies.
1242
+
1243
+ ### Scientific Significance of Event Lists
1244
+
1245
+ Event Lists allow astronomers to study the variability of astrophysical sources across a wide range of timescales:
1246
+ - **Fast Transients**: Sources like X-ray bursts, magnetar flares, or fast radio bursts, which brighten and dim on millisecond-to-minute scales.
1247
+ - **Quasi-Periodic Oscillations (QPOs)**: Oscillations in black hole and neutron star systems that vary unpredictably around a central frequency.
1248
+ - **Stochastic Variability**: Random fluctuations in brightness, often associated with accretion processes.
1249
+
1250
+ Additionally, Event Lists are fundamental for studying:
1251
+ - **Time Lags**: Delays between high- and low-energy photon emissions due to processes like reflection or turbulent flows in accretion disks.
1252
+ - **Spectral Timing**: Techniques that combine time and energy data to probe the physical processes near compact objects.
1253
+
1254
+ ### Anatomy of an Event List
1255
+
1256
+ An Event List is often stored as a FITS (Flexible Image Transport System) file, with each row in the table corresponding to a single detected photon. The table contains columns for various attributes:
1257
+ - **Time**: Precise timestamp of the event (e.g., in seconds or Modified Julian Date).
1258
+ - **Energy or PI Channel**: Photon energy or pulse invariant channel.
1259
+ - **GTIs**: Intervals of valid observation time.
1260
+ - **Spatial Information** (optional): Detector coordinates or celestial coordinates.
1261
+
1262
+ ### How Event Lists are Used
1263
+
1264
+ Event Lists are typically processed and filtered to remove invalid events or background noise. They can then be converted into:
1265
+ - **Light Curves**: Binned time series of photon counts.
1266
+ - **Spectra**: Energy distributions of detected photons.
1267
+ - **Power Spectra**: Frequency-domain representations of variability.
1268
+
1269
+ ### Key Terms in Event Lists
1270
+
1271
+ - **Photon Time of Arrival (TOA)**: The recorded time when a photon hits the detector.
1272
+ - **Good Time Intervals (GTIs)**: Periods when the instrument was actively recording valid data.
1273
+ - **Pulse Invariant (PI) Channel**: A detector-specific channel number that maps to the photon’s energy.
1274
+ - **RMF File**: Response Matrix File, used to calibrate PI channels into physical energy values (e.g., keV).
1275
+ - **FITS Format**: The standard file format for Event Lists in high-energy astrophysics.
1276
+
1277
+ ### Example: Event List Data Structure
1278
+
1279
+ A typical Event List in FITS format contains columns like:
1280
+ ```
1281
+ TIME PI ENERGY GTI
1282
+ ---------------------------------
1283
+ 0.0012 12 2.3 keV [0, 100]
1284
+ 0.0034 15 3.1 keV [0, 100]
1285
+ 0.0048 10 1.8 keV [0, 100]
1286
+ ```
1287
+
1288
+ ### Advantages of Event Lists
1289
+ - **High Precision**: Tracks individual photon events without binning, preserving maximum information.
1290
+ - **Flexibility**: Can be transformed into various forms (e.g., light curves, spectra) for different analyses.
1291
+ - **Time-Energy Data**: Enables advanced spectral-timing techniques.
1292
+
1293
+ ### Challenges and Considerations
1294
+ - **Dead Time**: Time intervals when the detector cannot record new events, affecting variability measurements.
1295
+ - **Instrumental Noise**: False events caused by electronics or background radiation.
1296
+ - **Time Resolution**: Limited by the instrument's precision in recording photon arrival times.
1297
+
1298
+ By understanding Event Lists, astronomers gain insight into the underlying physical processes driving variability in high-energy astrophysical sources.
1299
+
1300
+ ### References
1301
+ - van der Klis, M. (2006). "Rapid X-ray Variability."
1302
+ - Miniutti, G., et al. (2019). "Quasi-Periodic Eruptions in AGN."
1303
+ - Galloway, D., & Keek, L. (2021). "X-ray Bursts: Physics and Observations."
1304
+ - HEASARC Guidelines for FITS Event List Formats.
1305
+ <br><br>
1306
+ """
1307
+
1308
+
1309
+ eventlist_read_content = """
1310
+ ## Reading EventList
1311
+
1312
+ The `EventList.read` method is used to read event data files and load them as `EventList` objects in Stingray.
1313
+ This process involves parsing photon event data, such as arrival times, PI (Pulse Invariant) channels, and energy values.
1314
+
1315
+ ### Supported File Formats
1316
+ - **`pickle`**: Serialized Python objects (not recommended for long-term storage).
1317
+ - **`hea`** / **`ogip`**: FITS event files (commonly used in X-ray astronomy).
1318
+ - **Other Table-supported formats**: e.g., `hdf5`, `ascii.ecsv`, etc.
1319
+
1320
+ ### Parameters
1321
+ - **`filename` (str)**: Path to the file containing the event data.
1322
+ - **`fmt` (str)**: File format. Supported formats include:
1323
+ - `'pickle'`
1324
+ - `'hea'` or `'ogip'`
1325
+ - Table-compatible formats like `'hdf5'`, `'ascii.ecsv'`.
1326
+ - If `fmt` is not specified, the method attempts to infer the format based on the file extension.
1327
+ - **`rmf_file` (str, default=None)**:
1328
+ - Path to the RMF (Response Matrix File) for energy calibration.
1329
+ - Behavior:
1330
+ 1. **If `fmt="hea"` or `fmt="ogip"`**:
1331
+ - `rmf_file` is ignored during the `read` process.
1332
+ - You must apply it manually after loading using `convert_pi_to_energy`.
1333
+ 2. **If `fmt` is not `hea` or `ogip`**:
1334
+ - `rmf_file` can be directly specified in the `read` method for automatic energy calibration.
1335
+ - **`kwargs` (dict)**:
1336
+ - Additional parameters passed to the FITS reader (`load_events_and_gtis`) for reading OGIP/HEASOFT-compatible event lists.
1337
+ - Example: `additional_columns` for specifying extra data columns to read.
1338
+
1339
+ ### Attributes in the Loaded EventList
1340
+ - **`time`**: Array of photon arrival times in seconds relative to `mjdref`.
1341
+ - **`energy`**: Array of photon energy values (if calibrated using `rmf_file`).
1342
+ - **`pi`**: Array of Pulse Invariant (PI) channels.
1343
+ - **`mjdref`**: Reference time (Modified Julian Date).
1344
+ - **`gtis`**: Good Time Intervals, defining valid observation periods.
1345
+
1346
+ ### Stingray Classes and Functions in Use
1347
+ Below are the key classes and methods from Stingray that are used during this process:
1348
+
1349
+ #### Class: `EventList`
1350
+ ```python
1351
+ from stingray.events import EventList
1352
+
1353
+ class EventList:
1354
+ def __init__(self, time=None, energy=None, pi=None, gti=None, mjdref=0, rmf_file=None):
1355
+ # Initializes the event list with time, energy, PI channels, and other parameters
1356
+ ```
1357
+
1358
+ #### Method: `EventList.read`
1359
+ ```python
1360
+ @classmethod
1361
+ def read(cls, filename, fmt=None, rmf_file=None, **kwargs):
1362
+ if fmt in ("hea", "ogip"):
1363
+ evt = FITSTimeseriesReader(filename, output_class=EventList, **kwargs)[:]
1364
+ if rmf_file:
1365
+ evt.convert_pi_to_energy(rmf_file) # Must be applied manually for hea/ogip
1366
+ return evt
1367
+ return super().read(filename, fmt=fmt)
1368
+ ```
1369
+
1370
+ #### Function: `convert_pi_to_energy`
1371
+ ```python
1372
+ def convert_pi_to_energy(self, rmf_file):
1373
+ self.energy = pi_to_energy(self.pi, rmf_file)
1374
+ ```
1375
+
1376
+ ### Example Usage
1377
+ ```python
1378
+ from stingray.events import EventList
1379
+
1380
+ # Reading an OGIP-compatible FITS file
1381
+ event_list = EventList.read("example.evt", fmt="ogip")
1382
+
1383
+ # Applying RMF manually after reading
1384
+ event_list.convert_pi_to_energy("example.rmf")
1385
+
1386
+ # Reading an HDF5 file with direct RMF calibration
1387
+ event_list = EventList.read("example.hdf5", fmt="hdf5", rmf_file="example.rmf")
1388
+
1389
+ # Accessing attributes
1390
+ print(event_list.time) # Photon arrival times
1391
+ print(event_list.energy) # Calibrated energy values (if rmf_file used)
1392
+ print(event_list.pi) # PI channels
1393
+ print(event_list.gtis) # Good Time Intervals
1394
+ ```
1395
+
1396
+ ### Important Notes
1397
+ 1. **FITS Event Files (`hea` or `ogip`)**:
1398
+ - `rmf_file` must be applied manually after loading:
1399
+ ```python
1400
+ event_list.convert_pi_to_energy("example.rmf")
1401
+ ```
1402
+ 2. **Energy Calibration**:
1403
+ - Ensure the file contains PI channel data for energy calibration.
1404
+ - Without PI channels, RMF calibration will not work, and energy values will remain `None`.
1405
+ 3. **Good Time Intervals (GTIs)**:
1406
+ - GTIs define valid observation periods and are automatically extracted from compatible files.
1407
+
1408
+ ### Common Issues
1409
+ - **Unsupported File Format**:
1410
+ Ensure the file extension and format (`fmt`) match.
1411
+ - **Energy Not Calibrated**:
1412
+ Check for PI channels and provide an RMF file if needed.
1413
+ - **Missing Columns**:
1414
+ For OGIP/HEASOFT-compatible files, ensure required columns (e.g., `time`, `PI`) are available.
1415
+
1416
+ ### Additional Parameters for Advanced Use
1417
+ - **`additional_columns`**:
1418
+ Specify extra columns to read from the file.
1419
+ Example:
1420
+ ```python
1421
+ event_list = EventList.read("example.fits", fmt="hea", additional_columns=["detector_id"])
1422
+ ```
1423
+
1424
+ <br><br>
1425
+ """
1426
+
1427
+ # Create the help box
1428
+ return HelpBox(
1429
+ title="Help Section",
1430
+ tabs_content={
1431
+ "Event Lists": pn.pane.Markdown(intro_content),
1432
+ "Reading EventList": pn.pane.Markdown(eventlist_read_content),
1433
+ },
1434
+ )
1435
+
1436
 
1437
 
1438
  def create_loadingdata_plots_area():
modules/Home/HomeContent.py CHANGED
@@ -337,8 +337,12 @@ def create_home_help_area() -> HelpBox:
337
  HelpBox
338
  An instance of HelpBox with combined help content.
339
  """
340
- help_content = f"{HOME_HELP_BOX_STRING}\n\n{DASHBOARD_HELP_CONTENT}"
341
- return HelpBox(help_content=help_content, title="Help Section")
 
 
 
 
342
 
343
 
344
  """ Footer Section """
 
337
  HelpBox
338
  An instance of HelpBox with combined help content.
339
  """
340
+
341
+ tabs_content = {
342
+ "1st": pn.pane.Markdown("")
343
+ }
344
+ # help_content = f"{HOME_HELP_BOX_STRING}\n\n{DASHBOARD_HELP_CONTENT}"
345
+ return HelpBox(tabs_content=tabs_content, title="Help Section")
346
 
347
 
348
  """ Footer Section """
utils/DashboardClasses.py CHANGED
@@ -369,15 +369,15 @@ class PlotsContainer(pn.viewable.Viewer):
369
 
370
  class HelpBox(pn.viewable.Viewer):
371
  """
372
- HelpBox class represents a box to display help or documentation content.
373
  """
374
 
375
- # Parameters for the title and content of the help box
376
  title: str = param.String(
377
  default="Help", doc="Title for the help box", allow_refs=True
378
  )
379
- help_content: str = param.String(
380
- default="", doc="Markdown content for the help box", allow_refs=True
381
  )
382
 
383
  def __init__(self, **params):
@@ -388,11 +388,17 @@ class HelpBox(pn.viewable.Viewer):
388
 
389
  def __panel__(self):
390
  """
391
- Returns the Panel layout for the help box, including a heading and Markdown content.
392
  """
393
- heading = pn.pane.Markdown(f"<h2> {self.title}</h2>")
394
- help_markdown = pn.pane.Markdown(self.help_content, sizing_mode="stretch_both")
395
- return pn.Column(heading, help_markdown, sizing_mode="stretch_both")
 
 
 
 
 
 
396
 
397
 
398
  class Footer(pn.viewable.Viewer):
 
369
 
370
  class HelpBox(pn.viewable.Viewer):
371
  """
372
+ HelpBox class represents a box to display help or documentation content with tab-like functionality.
373
  """
374
 
375
+ # Parameters for the title and tabbed content of the help box
376
  title: str = param.String(
377
  default="Help", doc="Title for the help box", allow_refs=True
378
  )
379
+ tabs_content: dict = param.Dict(
380
+ default={}, doc="Dictionary with tab names as keys and content as values", allow_refs=True
381
  )
382
 
383
  def __init__(self, **params):
 
388
 
389
  def __panel__(self):
390
  """
391
+ Returns the Panel layout for the help box, including a heading and tabbed content.
392
  """
393
+ heading = pn.pane.Markdown(f"<h2>{self.title}</h2>")
394
+
395
+ # Create tabs using the provided content
396
+ tabs = pn.Tabs(dynamic=True)
397
+ for tab_name, content in self.tabs_content.items():
398
+ tabs.append((tab_name, content))
399
+
400
+ return pn.Column(heading, tabs, sizing_mode="stretch_both")
401
+
402
 
403
 
404
  class Footer(pn.viewable.Viewer):
utils/dashboardClasses.py CHANGED
@@ -369,15 +369,15 @@ class PlotsContainer(pn.viewable.Viewer):
369
 
370
  class HelpBox(pn.viewable.Viewer):
371
  """
372
- HelpBox class represents a box to display help or documentation content.
373
  """
374
 
375
- # Parameters for the title and content of the help box
376
  title: str = param.String(
377
  default="Help", doc="Title for the help box", allow_refs=True
378
  )
379
- help_content: str = param.String(
380
- default="", doc="Markdown content for the help box", allow_refs=True
381
  )
382
 
383
  def __init__(self, **params):
@@ -388,11 +388,17 @@ class HelpBox(pn.viewable.Viewer):
388
 
389
  def __panel__(self):
390
  """
391
- Returns the Panel layout for the help box, including a heading and Markdown content.
392
  """
393
- heading = pn.pane.Markdown(f"<h2> {self.title}</h2>")
394
- help_markdown = pn.pane.Markdown(self.help_content, sizing_mode="stretch_both")
395
- return pn.Column(heading, help_markdown, sizing_mode="stretch_both")
 
 
 
 
 
 
396
 
397
 
398
  class Footer(pn.viewable.Viewer):
 
369
 
370
  class HelpBox(pn.viewable.Viewer):
371
  """
372
+ HelpBox class represents a box to display help or documentation content with tab-like functionality.
373
  """
374
 
375
+ # Parameters for the title and tabbed content of the help box
376
  title: str = param.String(
377
  default="Help", doc="Title for the help box", allow_refs=True
378
  )
379
+ tabs_content: dict = param.Dict(
380
+ default={}, doc="Dictionary with tab names as keys and content as values", allow_refs=True
381
  )
382
 
383
  def __init__(self, **params):
 
388
 
389
  def __panel__(self):
390
  """
391
+ Returns the Panel layout for the help box, including a heading and tabbed content.
392
  """
393
+ heading = pn.pane.Markdown(f"<h2>{self.title}</h2>")
394
+
395
+ # Create tabs using the provided content
396
+ tabs = pn.Tabs(dynamic=True)
397
+ for tab_name, content in self.tabs_content.items():
398
+ tabs.append((tab_name, content))
399
+
400
+ return pn.Column(heading, tabs, sizing_mode="stretch_both")
401
+
402
 
403
 
404
  class Footer(pn.viewable.Viewer):