Spaces:
Running
Running
Commit ·
44f8493
1
Parent(s): d9f3d42
data read is more robust
Browse files- explorer.py +1 -0
- modules/DataLoading/DataIngestion.py +108 -24
explorer.py
CHANGED
|
@@ -17,6 +17,7 @@ from utils.sidebar import create_sidebar
|
|
| 17 |
|
| 18 |
# Initialize panel extension
|
| 19 |
pn.extension('floatpanel', 'mathjax')
|
|
|
|
| 20 |
hv.extension('bokeh')
|
| 21 |
|
| 22 |
# Create a boolean status indicator
|
|
|
|
| 17 |
|
| 18 |
# Initialize panel extension
|
| 19 |
pn.extension('floatpanel', 'mathjax')
|
| 20 |
+
pn.extension('filedropper')
|
| 21 |
hv.extension('bokeh')
|
| 22 |
|
| 23 |
# Create a boolean status indicator
|
modules/DataLoading/DataIngestion.py
CHANGED
|
@@ -137,12 +137,14 @@ def create_loadingdata_warning_box(content):
|
|
| 137 |
return WarningBox(warning_content=content)
|
| 138 |
|
| 139 |
|
| 140 |
-
def
|
| 141 |
event,
|
| 142 |
file_selector,
|
| 143 |
filename_input,
|
| 144 |
format_input,
|
| 145 |
format_checkbox,
|
|
|
|
|
|
|
| 146 |
output_box_container,
|
| 147 |
warning_box_container,
|
| 148 |
warning_handler,
|
|
@@ -171,7 +173,7 @@ def load_event_data(
|
|
| 171 |
- Requires that the number of formats matches the number of files unless default format is used.
|
| 172 |
|
| 173 |
Example:
|
| 174 |
-
>>>
|
| 175 |
>>> len(loaded_event_data)
|
| 176 |
1 # Assuming one file was loaded
|
| 177 |
"""
|
|
@@ -213,6 +215,63 @@ def load_event_data(
|
|
| 213 |
]
|
| 214 |
return
|
| 215 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 216 |
try:
|
| 217 |
loaded_files = []
|
| 218 |
for file_path, file_name, file_format in zip(file_paths, filenames, formats):
|
|
@@ -224,7 +283,7 @@ def load_event_data(
|
|
| 224 |
]
|
| 225 |
return
|
| 226 |
|
| 227 |
-
event_list = EventList.read(file_path, file_format)
|
| 228 |
loaded_event_data.append((file_name, event_list))
|
| 229 |
loaded_files.append(
|
| 230 |
f"File '{file_path}' loaded successfully as '{file_name}' with format '{file_format}'."
|
|
@@ -404,7 +463,7 @@ def delete_selected_files(
|
|
| 404 |
# Define allowed extensions for deletion
|
| 405 |
allowed_extensions = {
|
| 406 |
".pkl", ".pickle", ".fits", ".evt", ".h5", ".hdf5",
|
| 407 |
-
".ecsv", ".txt", ".dat", ".csv", ".vot", ".tex", ".html"
|
| 408 |
}
|
| 409 |
if not file_selector.value:
|
| 410 |
output_box_container[:] = [
|
|
@@ -416,12 +475,12 @@ def delete_selected_files(
|
|
| 416 |
|
| 417 |
file_paths = file_selector.value
|
| 418 |
deleted_files = []
|
| 419 |
-
restricted_files = []
|
| 420 |
for file_path in file_paths:
|
| 421 |
-
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
|
|
|
|
| 425 |
continue
|
| 426 |
|
| 427 |
try:
|
|
@@ -431,17 +490,6 @@ def delete_selected_files(
|
|
| 431 |
deleted_files.append(f"File '{file_path}' deleted successfully.")
|
| 432 |
except Exception as e:
|
| 433 |
deleted_files.append(f"An error occurred while deleting '{file_path}': {e}")
|
| 434 |
-
|
| 435 |
-
# Create messages for deleted and restricted files
|
| 436 |
-
messages = []
|
| 437 |
-
if deleted_files:
|
| 438 |
-
messages.append("\n".join(deleted_files))
|
| 439 |
-
if restricted_files:
|
| 440 |
-
messages.append(
|
| 441 |
-
"The following files were not deleted because their extensions are not allowed:\n" +
|
| 442 |
-
"\n".join(restricted_files)
|
| 443 |
-
)
|
| 444 |
-
|
| 445 |
output_box_container[:] = [create_loadingdata_output_box("\n".join(deleted_files))]
|
| 446 |
if warning_handler.warnings:
|
| 447 |
warning_box_container[:] = [
|
|
@@ -796,8 +844,12 @@ def create_loading_tab(output_box_container, warning_box_container, warning_hand
|
|
| 796 |
>>> isinstance(tab, pn.Column)
|
| 797 |
True
|
| 798 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
| 799 |
file_selector = pn.widgets.FileSelector(
|
| 800 |
-
|
| 801 |
)
|
| 802 |
filename_input = pn.widgets.TextInput(
|
| 803 |
name="Enter File Names",
|
|
@@ -810,7 +862,7 @@ def create_loading_tab(output_box_container, warning_box_container, warning_hand
|
|
| 810 |
width=400,
|
| 811 |
)
|
| 812 |
format_checkbox = pn.widgets.Checkbox(
|
| 813 |
-
name="Use default format (ogip for
|
| 814 |
)
|
| 815 |
load_button = pn.widgets.Button(name="Load Event Data", button_type="primary")
|
| 816 |
save_button = pn.widgets.Button(name="Save Loaded Data", button_type="success")
|
|
@@ -835,6 +887,34 @@ def create_loading_tab(output_box_container, warning_box_container, warning_hand
|
|
| 835 |
position="bottom",
|
| 836 |
)
|
| 837 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 838 |
|
| 839 |
def on_load_click(event):
|
| 840 |
# Clear previous outputs and warnings
|
|
@@ -843,12 +923,14 @@ def create_loading_tab(output_box_container, warning_box_container, warning_hand
|
|
| 843 |
warning_handler.warnings.clear()
|
| 844 |
warnings.resetwarnings()
|
| 845 |
|
| 846 |
-
|
| 847 |
event,
|
| 848 |
file_selector,
|
| 849 |
filename_input,
|
| 850 |
format_input,
|
| 851 |
format_checkbox,
|
|
|
|
|
|
|
| 852 |
output_box_container,
|
| 853 |
warning_box_container,
|
| 854 |
warning_handler,
|
|
@@ -912,11 +994,13 @@ def create_loading_tab(output_box_container, warning_box_container, warning_hand
|
|
| 912 |
clear_button.on_click(on_clear_click)
|
| 913 |
|
| 914 |
first_column = pn.Column(
|
| 915 |
-
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="
|
| 916 |
file_selector,
|
| 917 |
pn.Row(filename_input, tooltip_file),
|
| 918 |
pn.Row(format_input, tooltip_format),
|
| 919 |
format_checkbox,
|
|
|
|
|
|
|
| 920 |
pn.Row(load_button, save_button, delete_button, preview_button, clear_button),
|
| 921 |
pn.pane.Markdown("<br/>"),
|
| 922 |
width_policy="min",
|
|
|
|
| 137 |
return WarningBox(warning_content=content)
|
| 138 |
|
| 139 |
|
| 140 |
+
def read_event_data(
|
| 141 |
event,
|
| 142 |
file_selector,
|
| 143 |
filename_input,
|
| 144 |
format_input,
|
| 145 |
format_checkbox,
|
| 146 |
+
rmf_file_dropper,
|
| 147 |
+
additional_columns_input,
|
| 148 |
output_box_container,
|
| 149 |
warning_box_container,
|
| 150 |
warning_handler,
|
|
|
|
| 173 |
- Requires that the number of formats matches the number of files unless default format is used.
|
| 174 |
|
| 175 |
Example:
|
| 176 |
+
>>> read_event_data(event, file_selector, filename_input, format_input, format_checkbox, ...)
|
| 177 |
>>> len(loaded_event_data)
|
| 178 |
1 # Assuming one file was loaded
|
| 179 |
"""
|
|
|
|
| 215 |
]
|
| 216 |
return
|
| 217 |
|
| 218 |
+
def read_event_data(
|
| 219 |
+
event,
|
| 220 |
+
file_selector,
|
| 221 |
+
filename_input,
|
| 222 |
+
format_input,
|
| 223 |
+
format_checkbox,
|
| 224 |
+
rmf_file_dropper,
|
| 225 |
+
additional_columns_input,
|
| 226 |
+
output_box_container,
|
| 227 |
+
warning_box_container,
|
| 228 |
+
warning_handler,
|
| 229 |
+
):
|
| 230 |
+
"""
|
| 231 |
+
Load event data from selected files with extended EventList.read functionality,
|
| 232 |
+
supporting FileDropper for RMF files and additional columns.
|
| 233 |
+
"""
|
| 234 |
+
# Validation for required inputs
|
| 235 |
+
if not file_selector.value:
|
| 236 |
+
output_box_container[:] = [
|
| 237 |
+
create_loadingdata_output_box(
|
| 238 |
+
"No file selected. Please select a file to upload."
|
| 239 |
+
)
|
| 240 |
+
]
|
| 241 |
+
return
|
| 242 |
+
|
| 243 |
+
file_paths = file_selector.value
|
| 244 |
+
filenames = (
|
| 245 |
+
[name.strip() for name in filename_input.value.split(",")]
|
| 246 |
+
if filename_input.value
|
| 247 |
+
else []
|
| 248 |
+
)
|
| 249 |
+
formats = (
|
| 250 |
+
[fmt.strip() for fmt in format_input.value.split(",")]
|
| 251 |
+
if format_input.value
|
| 252 |
+
else []
|
| 253 |
+
)
|
| 254 |
+
|
| 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 = (
|
| 270 |
+
[col.strip() for col in additional_columns_input.value.split(",")]
|
| 271 |
+
if additional_columns_input.value
|
| 272 |
+
else None
|
| 273 |
+
)
|
| 274 |
+
|
| 275 |
try:
|
| 276 |
loaded_files = []
|
| 277 |
for file_path, file_name, file_format in zip(file_paths, filenames, formats):
|
|
|
|
| 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}'."
|
|
|
|
| 463 |
# Define allowed extensions for deletion
|
| 464 |
allowed_extensions = {
|
| 465 |
".pkl", ".pickle", ".fits", ".evt", ".h5", ".hdf5",
|
| 466 |
+
".ecsv", ".txt", ".dat", ".csv", ".vot", ".tex", ".html", ".gz"
|
| 467 |
}
|
| 468 |
if not file_selector.value:
|
| 469 |
output_box_container[:] = [
|
|
|
|
| 475 |
|
| 476 |
file_paths = file_selector.value
|
| 477 |
deleted_files = []
|
|
|
|
| 478 |
for file_path in file_paths:
|
| 479 |
+
|
| 480 |
+
if not any(file_path.endswith(ext) for ext in allowed_extensions):
|
| 481 |
+
deleted_files.append(
|
| 482 |
+
f"Cannot delete file '{file_path}': File type is not allowed for deletion."
|
| 483 |
+
)
|
| 484 |
continue
|
| 485 |
|
| 486 |
try:
|
|
|
|
| 490 |
deleted_files.append(f"File '{file_path}' deleted successfully.")
|
| 491 |
except Exception as e:
|
| 492 |
deleted_files.append(f"An error occurred while deleting '{file_path}': {e}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 493 |
output_box_container[:] = [create_loadingdata_output_box("\n".join(deleted_files))]
|
| 494 |
if warning_handler.warnings:
|
| 495 |
warning_box_container[:] = [
|
|
|
|
| 844 |
>>> isinstance(tab, pn.Column)
|
| 845 |
True
|
| 846 |
"""
|
| 847 |
+
|
| 848 |
+
# Get the user's home directory
|
| 849 |
+
home_directory = os.path.expanduser("~")
|
| 850 |
+
|
| 851 |
file_selector = pn.widgets.FileSelector(
|
| 852 |
+
home_directory, only_files=True, name="Select File", show_hidden=True
|
| 853 |
)
|
| 854 |
filename_input = pn.widgets.TextInput(
|
| 855 |
name="Enter File Names",
|
|
|
|
| 862 |
width=400,
|
| 863 |
)
|
| 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")
|
|
|
|
| 887 |
position="bottom",
|
| 888 |
)
|
| 889 |
)
|
| 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(
|
| 915 |
+
name="Additional Columns (optional)", placeholder="Comma-separated column names"
|
| 916 |
+
)
|
| 917 |
+
|
| 918 |
|
| 919 |
def on_load_click(event):
|
| 920 |
# Clear previous outputs and warnings
|
|
|
|
| 923 |
warning_handler.warnings.clear()
|
| 924 |
warnings.resetwarnings()
|
| 925 |
|
| 926 |
+
read_event_data(
|
| 927 |
event,
|
| 928 |
file_selector,
|
| 929 |
filename_input,
|
| 930 |
format_input,
|
| 931 |
format_checkbox,
|
| 932 |
+
rmf_file_dropper,
|
| 933 |
+
additional_columns_input,
|
| 934 |
output_box_container,
|
| 935 |
warning_box_container,
|
| 936 |
warning_handler,
|
|
|
|
| 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",
|