ajsbsd commited on
Commit
71f864d
·
verified ·
1 Parent(s): 6e6f8fe

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +8 -32
app.py CHANGED
@@ -4,24 +4,19 @@ from neuralop.models import FNO
4
  import matplotlib.pyplot as plt
5
  import numpy as np
6
  import os
7
- # import spaces # No longer needed if running purely on CPU and not using @spaces.GPU()
8
  from huggingface_hub import hf_hub_download
9
 
10
- # --- Configuration ---
11
- MODEL_PATH = "fno_ckpt_single_res" # This model file still needs to be in your Space's repo
12
- HF_DATASET_REPO_ID = "ajsbsd/navier-stokes-2d-dataset" # Your new repo ID
13
  HF_DATASET_FILENAME = "navier_stokes_2d.pt"
14
 
15
- # --- Global Variables for Model and Data (loaded once) ---
16
  MODEL = None
17
  FULL_DATASET_X = None
18
 
19
- # --- Function to Download Dataset from HF Hub ---
20
  def download_file_from_hf_hub(repo_id, filename):
21
  """Downloads a file from Hugging Face Hub."""
22
  print(f"Downloading {filename} from {repo_id} on Hugging Face Hub...")
23
  try:
24
- # hf_hub_download returns the local path to the downloaded file
25
  local_path = hf_hub_download(repo_id=repo_id, filename=filename)
26
  print(f"Downloaded {filename} to {local_path} successfully.")
27
  return local_path
@@ -29,8 +24,6 @@ def download_file_from_hf_hub(repo_id, filename):
29
  print(f"Error downloading file from HF Hub: {e}")
30
  raise gr.Error(f"Failed to download dataset from Hugging Face Hub: {e}")
31
 
32
-
33
- # --- 1. Model Loading Function (Loads to CPU, device transfer handled in run_inference) ---
34
  def load_model():
35
  """Loads the pre-trained FNO model to CPU."""
36
  global MODEL
@@ -45,7 +38,6 @@ def load_model():
45
  raise gr.Error(f"Failed to load model: {e}")
46
  return MODEL
47
 
48
- # --- 2. Dataset Loading Function ---
49
  def load_dataset():
50
  """Downloads and loads the initial conditions dataset from HF Hub."""
51
  global FULL_DATASET_X
@@ -56,11 +48,7 @@ def load_dataset():
56
  data = torch.load(local_dataset_path, map_location='cpu')
57
  if isinstance(data, dict) and 'x' in data:
58
  FULL_DATASET_X = data['x']
59
- elif isinstance(dYou can easily add that blurb by inserting a `gr.Markdown()` component within the same `gr.Column()` as your `sample_input_slider` and `run_button`. This effectively places it within Gradio's "flexbox" layout, ensuring it's always visible below the slider and button.
60
-
61
- Here's your `app.py` code with the blurb added in the correct place. I've also updated the `run_inference` function to explicitly target `torch.device("cpu")` and removed the `@spaces.GPU()` decorator, which aligns with your successful run on ZeroCPU.
62
-
63
- ```pythonata, torch.Tensor):
64
  FULL_DATASET_X = data
65
  else:
66
  raise ValueError("Unknown dataset format or 'x' key missing.")
@@ -70,41 +58,34 @@ Here's your `app.py` code with the blurb added in the correct place. I've also u
70
  raise gr.Error(f"Failed to load dataset from local file: {e}")
71
  return FULL_DATASET_X
72
 
73
- # --- 3. Inference Function for Gradio ---
74
- # Removed @spaces.GPU() decorator as you're running on ZeroCPU
75
  def run_inference(sample_index: int):
76
  """
77
  Performs inference for a selected sample index from the dataset on CPU.
78
  Returns two Matplotlib figures: one for input, one for output.
79
  """
80
- # Determine the target device (always CPU for ZeroCPU space)
81
- device = torch.device("cpu") # Explicitly set to CPU as you're on ZeroCPU
82
 
83
- model = load_model() # Model is initially loaded to CPU
84
 
85
- # Model device check is still good practice, even if always CPU here
86
  if next(model.parameters()).device != device:
87
  model.to(device)
88
- print(f"Model moved to {device} within run_inference.") # Will now print 'Model moved to cpu...'
89
 
90
  dataset = load_dataset()
91
 
92
  if not (0 <= sample_index < dataset.shape[0]):
93
  raise gr.Error(f"Sample index out of range. Please choose between 0 and {dataset.shape[0]-1}.")
94
 
95
- # Move input tensor to the correct device
96
  single_initial_condition = dataset[sample_index:sample_index+1, :, :].unsqueeze(1).to(device)
97
- print(f"Input moved to {device}.") # Will now print 'Input moved to cpu.'
98
 
99
  print(f"Running inference for sample index {sample_index}...")
100
- with torch.no_grad(): # Disable gradient calculations for inference
101
  predicted_solution = model(single_initial_condition)
102
 
103
- # Move results back to CPU for plotting with Matplotlib (already on CPU now)
104
  input_numpy = single_initial_condition.squeeze().cpu().numpy()
105
  output_numpy = predicted_solution.squeeze().cpu().numpy()
106
 
107
- # Create Matplotlib figures
108
  fig_input, ax_input = plt.subplots()
109
  im_input = ax_input.imshow(input_numpy, cmap='viridis')
110
  ax_input.set_title(f"Initial Condition (Sample {sample_index})")
@@ -119,7 +100,6 @@ def run_inference(sample_index: int):
119
 
120
  return fig_input, fig_output
121
 
122
- # --- Gradio Interface Setup (MODIFIED to add blurb) ---
123
  with gr.Blocks() as demo:
124
  gr.Markdown(
125
  """
@@ -140,14 +120,12 @@ with gr.Blocks() as demo:
140
  )
141
  run_button = gr.Button("Generate Solution")
142
 
143
- # --- ADDED BLURB HERE ---
144
  gr.Markdown(
145
  """
146
  ### Project Inspiration
147
  This Hugging Face Space demonstrates the concepts and models from the research paper **'Principled approaches for extending neural architectures to function spaces for operator learning'** (available as a preprint on [arXiv](https://arxiv.org/abs/2506.10973)). The underlying code for the neural operators and the experiments can be explored further in the associated [GitHub repository](https://github.com/neuraloperator/NNs-to-NOs). The Navier-Stokes dataset used for training and inference, crucial for these fluid dynamics simulations, is openly accessible and citable via [Zenodo](https://zenodo.org/records/12825163).
148
  """
149
  )
150
- # --- END ADDED BLURB ---
151
 
152
  with gr.Column():
153
  input_image_plot = gr.Plot(label="Selected Initial Condition")
@@ -160,10 +138,8 @@ with gr.Blocks() as demo:
160
  )
161
 
162
  def load_initial_data_and_predict():
163
- # These functions are called during main process startup (CPU)
164
  load_model()
165
  load_dataset()
166
- # The actual inference call here will now run on CPU
167
  return run_inference(0)
168
 
169
  demo.load(load_initial_data_and_predict, inputs=None, outputs=[input_image_plot, output_image_plot])
 
4
  import matplotlib.pyplot as plt
5
  import numpy as np
6
  import os
 
7
  from huggingface_hub import hf_hub_download
8
 
9
+ MODEL_PATH = "fno_ckpt_single_res"
10
+ HF_DATASET_REPO_ID = "ajsbsd/navier-stokes-2d-dataset"
 
11
  HF_DATASET_FILENAME = "navier_stokes_2d.pt"
12
 
 
13
  MODEL = None
14
  FULL_DATASET_X = None
15
 
 
16
  def download_file_from_hf_hub(repo_id, filename):
17
  """Downloads a file from Hugging Face Hub."""
18
  print(f"Downloading {filename} from {repo_id} on Hugging Face Hub...")
19
  try:
 
20
  local_path = hf_hub_download(repo_id=repo_id, filename=filename)
21
  print(f"Downloaded {filename} to {local_path} successfully.")
22
  return local_path
 
24
  print(f"Error downloading file from HF Hub: {e}")
25
  raise gr.Error(f"Failed to download dataset from Hugging Face Hub: {e}")
26
 
 
 
27
  def load_model():
28
  """Loads the pre-trained FNO model to CPU."""
29
  global MODEL
 
38
  raise gr.Error(f"Failed to load model: {e}")
39
  return MODEL
40
 
 
41
  def load_dataset():
42
  """Downloads and loads the initial conditions dataset from HF Hub."""
43
  global FULL_DATASET_X
 
48
  data = torch.load(local_dataset_path, map_location='cpu')
49
  if isinstance(data, dict) and 'x' in data:
50
  FULL_DATASET_X = data['x']
51
+ elif isinstance(data, torch.Tensor):
 
 
 
 
52
  FULL_DATASET_X = data
53
  else:
54
  raise ValueError("Unknown dataset format or 'x' key missing.")
 
58
  raise gr.Error(f"Failed to load dataset from local file: {e}")
59
  return FULL_DATASET_X
60
 
 
 
61
  def run_inference(sample_index: int):
62
  """
63
  Performs inference for a selected sample index from the dataset on CPU.
64
  Returns two Matplotlib figures: one for input, one for output.
65
  """
66
+ device = torch.device("cpu")
 
67
 
68
+ model = load_model()
69
 
 
70
  if next(model.parameters()).device != device:
71
  model.to(device)
72
+ print(f"Model moved to {device} within run_inference.")
73
 
74
  dataset = load_dataset()
75
 
76
  if not (0 <= sample_index < dataset.shape[0]):
77
  raise gr.Error(f"Sample index out of range. Please choose between 0 and {dataset.shape[0]-1}.")
78
 
 
79
  single_initial_condition = dataset[sample_index:sample_index+1, :, :].unsqueeze(1).to(device)
80
+ print(f"Input moved to {device}.")
81
 
82
  print(f"Running inference for sample index {sample_index}...")
83
+ with torch.no_grad():
84
  predicted_solution = model(single_initial_condition)
85
 
 
86
  input_numpy = single_initial_condition.squeeze().cpu().numpy()
87
  output_numpy = predicted_solution.squeeze().cpu().numpy()
88
 
 
89
  fig_input, ax_input = plt.subplots()
90
  im_input = ax_input.imshow(input_numpy, cmap='viridis')
91
  ax_input.set_title(f"Initial Condition (Sample {sample_index})")
 
100
 
101
  return fig_input, fig_output
102
 
 
103
  with gr.Blocks() as demo:
104
  gr.Markdown(
105
  """
 
120
  )
121
  run_button = gr.Button("Generate Solution")
122
 
 
123
  gr.Markdown(
124
  """
125
  ### Project Inspiration
126
  This Hugging Face Space demonstrates the concepts and models from the research paper **'Principled approaches for extending neural architectures to function spaces for operator learning'** (available as a preprint on [arXiv](https://arxiv.org/abs/2506.10973)). The underlying code for the neural operators and the experiments can be explored further in the associated [GitHub repository](https://github.com/neuraloperator/NNs-to-NOs). The Navier-Stokes dataset used for training and inference, crucial for these fluid dynamics simulations, is openly accessible and citable via [Zenodo](https://zenodo.org/records/12825163).
127
  """
128
  )
 
129
 
130
  with gr.Column():
131
  input_image_plot = gr.Plot(label="Selected Initial Condition")
 
138
  )
139
 
140
  def load_initial_data_and_predict():
 
141
  load_model()
142
  load_dataset()
 
143
  return run_inference(0)
144
 
145
  demo.load(load_initial_data_and_predict, inputs=None, outputs=[input_image_plot, output_image_plot])