Bushra346 commited on
Commit
fa485bd
·
verified ·
1 Parent(s): 6bf0f73

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +14 -190
app.py CHANGED
@@ -1,14 +1,7 @@
1
- # app.py
2
  import gradio as gr
3
- import pandas as pd
4
- import numpy as np
5
- import matplotlib.pyplot as plt
6
  import os
7
- import base64
8
- import requests # Assuming requests is used in query_gpt5
9
-
10
- # Ensure matplotlib uses an inline backend (though not strictly needed for saving files)
11
- # %matplotlib inline # This is a Colab magic command, not standard Python. Remove for app.py
12
 
13
  # Assuming your API key is set as an environment variable in Hugging Face Spaces secrets
14
  API_KEY = os.getenv("AIML_API_KEY")
@@ -19,9 +12,9 @@ def query_gpt5(user_input):
19
  return "API Key not set. Please set AIML_API_KEY environment variable."
20
  headers = {"Authorization": f"Bearer {API_KEY}"}
21
  data = {
22
- "model": "openai/gpt-4o",
23
  "messages": [
24
- {"role": "system", "content": "You are an expert in battery materials and sustainable energy."},
25
  {"role": "user", "content": user_input}
26
  ]
27
  }
@@ -40,185 +33,16 @@ def query_gpt5(user_input):
40
  except Exception as e:
41
  return f"An error occurred during API query: {e}"
42
 
43
-
44
- # Define the analyze_eis function (modified to return file paths)
45
- def analyze_eis_and_get_text(eis_file):
46
- if eis_file is None:
47
- return "Please upload an EIS data file.", None, None
48
-
49
- try:
50
- # Load the uploaded file into a pandas DataFrame
51
- # For deployment, Gradio provides a file-like object, access path via .name
52
- df_eis = pd.read_csv(eis_file.name)
53
-
54
- # Ensure required columns exist
55
- if 'Frequency (Hz)' not in df_eis.columns or 'Z_real (ohm)' not in df_eis.columns or 'Z_imag (ohm)' not in df_eis.columns:
56
- return "Uploaded file must contain 'Frequency (Hz)', 'Z_real (ohm)', and 'Z_imag (ohm)' columns.", None, None
57
-
58
- # Calculate magnitude and phase
59
- df_eis['Impedance Magnitude (ohm)'] = np.sqrt(df_eis['Z_real (ohm)']**2 + df_eis['Z_imag (ohm)']**2)
60
- df_eis['Impedance Phase (deg)'] = np.arctan2(df_eis['Z_imag (ohm)'], df_eis['Z_real (ohm)']) * 180 / np.pi
61
-
62
- # Generate Nyquist Plot
63
- plt.figure(figsize=(6, 5))
64
- plt.plot(df_eis['Z_real (ohm)'], -df_eis['Z_imag (ohm)'], marker='o', markersize=4, linestyle='-')
65
- plt.xlabel('Z_real (ohm)')
66
- plt.ylabel('-Z_imag (ohm)')
67
- plt.title('Nyquist Plot')
68
- plt.gca().set_aspect('equal', adjustable='box')
69
- plt.grid(True)
70
- nyquist_plot_path = "nyquist_plot.png"
71
- plt.savefig(nyquist_plot_path)
72
- plt.close() # Close the plot figure to free memory
73
-
74
- # Generate Bode Plots
75
- plt.figure(figsize=(10, 7))
76
-
77
- # Magnitude Plot
78
- plt.subplot(2, 1, 1)
79
- plt.loglog(df_eis['Frequency (Hz)'], df_eis['Impedance Magnitude (ohm)'], marker='o', markersize=4, linestyle='-')
80
- plt.xlabel('Frequency (Hz)')
81
- plt.ylabel('Impedance Magnitude (ohm)')
82
- plt.title('Bode Plot - Magnitude')
83
- plt.grid(True, which="both", ls="--")
84
-
85
- # Phase Plot
86
- plt.subplot(2, 1, 2)
87
- plt.semilogx(df_eis['Frequency (Hz)'], df_eis['Impedance Phase (deg)'], marker='o', markersize=4, linestyle='-')
88
- plt.xlabel('Frequency (Hz)')
89
- plt.ylabel('Phase (deg)')
90
- plt.title('Bode Plot - Phase')
91
- plt.grid(True, which="both", ls="--")
92
-
93
- plt.tight_layout()
94
- bode_plots_path = "bode_plots.png"
95
- plt.savefig(bode_plots_path)
96
- plt.close() # Close the plot figure
97
-
98
- # Generate EIS analysis text
99
- nyquist_description = "Nyquist plot analysis:\n"
100
- # Handle potential empty dataframe or single point data
101
- if not df_eis.empty:
102
- rs_high_freq = df_eis['Z_real (ohm)'].iloc[-1]
103
- nyquist_description += f"- High-frequency intercept (series resistance): {rs_high_freq:.2f} ohm.\n"
104
-
105
- # Simple approximation for charge transfer resistance
106
- if len(df_eis) > 1:
107
- mid_freq_real = df_eis['Z_real (ohm)'].iloc[len(df_eis)//2]
108
- rct_approx = mid_freq_real - rs_high_freq
109
- nyquist_description += f"- Semicircle observed in the mid-frequency range, indicating charge transfer processes. Approximate charge transfer resistance: {rct_approx:.2f} ohm.\n"
110
- else:
111
- nyquist_description += "- Not enough data points to approximate semicircle.\n"
112
-
113
- # Describe low-frequency behavior (Warburg impedance)
114
- if len(df_eis) > 1:
115
- low_freq_z = df_eis.iloc[:5] # Look at the first few low frequency points
116
- if len(low_freq_z) > 1:
117
- slopes = (low_freq_z['Z_imag (ohm)'].diff() / low_freq_z['Z_real (ohm)'].diff()).dropna()
118
- if any(abs(slope + 1) < 0.2 for slope in slopes): # Using a tolerance
119
- nyquist_description += "- Low-frequency tail shows a Warburg impedance behavior, characteristic of diffusion processes.\n"
120
- else:
121
- nyquist_description += "- Low-frequency behavior observed.\n"
122
- else:
123
- nyquist_description += "- Not enough low-frequency data points to determine Warburg behavior.\n"
124
- else:
125
- nyquist_description += "- Not enough data points for low-frequency analysis.\n"
126
-
127
-
128
- bode_mag_description = "Bode Magnitude plot analysis:\n"
129
- bode_mag_description += f"- At high frequencies, the impedance magnitude is around {df_eis['Impedance Magnitude (ohm)'].iloc[-1]:.2f} ohm.\n"
130
- bode_mag_description += f"- At low frequencies, the impedance magnitude increases significantly, reaching {df_eis['Impedance Magnitude (ohm)'].iloc[0]:.2f} ohm, indicating capacitive or diffusion-limited behavior.\n"
131
- bode_mag_description += "- The magnitude plot shows a decrease with frequency in the mid-range, followed by an increase at low frequencies.\n"
132
-
133
- bode_phase_description = "Bode Phase plot analysis:\n"
134
- bode_phase_description += f"- At high frequencies, the phase angle is around {df_eis['Impedance Phase (deg)'].iloc[-1]:.2f} degrees, close to 0.\n"
135
- if len(df_eis) > 1:
136
- min_phase_idx = df_eis['Impedance Phase (deg)'].idxmin()
137
- min_phase_freq = df_eis['Frequency (Hz)'].iloc[min_phase_idx]
138
- min_phase_value = df_eis['Impedance Phase (deg)'].iloc[min_phase_idx]
139
- bode_phase_description += f"- A phase minimum of {min_phase_value:.2f} degrees is observed around {min_phase_freq:.4f} Hz, corresponding to charge transfer processes.\n"
140
- else:
141
- bode_phase_description += "- Not enough data points to identify phase minimum.\n"
142
- bode_phase_description += f"- At low frequencies, the phase angle approaches {df_eis['Impedance Phase (deg)'].iloc[0]:.2f} degrees, consistent with capacitive or diffusion behavior.\n"
143
- else:
144
- nyquist_description += "- No data available for analysis.\n"
145
- bode_mag_description = "Bode Magnitude plot analysis:\n- No data available for analysis.\n"
146
- bode_phase_description = "Bode Phase plot analysis:\n- No data available for analysis.\n"
147
-
148
-
149
- eis_analysis_text = "Electrochemical Impedance Spectroscopy (EIS) Analysis:\n\n" + \
150
- nyquist_description + "\n" + \
151
- bode_mag_description + "\n" + \
152
- bode_phase_description + "\n" + \
153
- "Note: Parameters like charge transfer resistance and Warburg impedance are estimated from visual features; precise values would require equivalent circuit fitting."
154
-
155
- # Return the analysis text and paths to the saved plot files
156
- return eis_analysis_text, nyquist_plot_path, bode_plots_path
157
-
158
- except Exception as e:
159
- # Clean up generated files if an error occurs
160
- if os.path.exists("nyquist_plot.png"):
161
- os.remove("nyquist_plot.png")
162
- if os.path.exists("bode_plots.png"):
163
- os.remove("bode_plots.png")
164
- return f"Error processing EIS data: {e}", None, None
165
-
166
-
167
- # Modify the material_analysis function to accept EIS analysis text
168
- def material_analysis(query, eis_analysis_text):
169
- combined_query = query
170
- if eis_analysis_text and eis_analysis_text != "Please upload an EIS data file.":
171
- combined_query = query + "\n\nEIS Analysis:\n" + eis_analysis_text
172
-
173
- answer = query_gpt5(combined_query)
174
- return answer
175
-
176
-
177
- # Define the integrated function that first analyzes EIS and then queries the AI
178
- def process_eis_and_query_ai(eis_file, ai_query):
179
- # Analyze EIS data - this will save plot files and return analysis text
180
- eis_analysis_text, nyquist_plot_path, bode_plots_path = analyze_eis_and_get_text(eis_file)
181
-
182
- # Query AI with the analysis text
183
- # The AI query should only proceed if there's a valid AI query input
184
- ai_response_text = ""
185
- if ai_query:
186
- ai_response_text = material_analysis(ai_query, eis_analysis_text)
187
-
188
- # Return all outputs
189
- # Ensure paths are returned even if AI query is empty
190
- return eis_analysis_text, nyquist_plot_path, bode_plots_path, ai_response_text
191
-
192
-
193
- # Define Gradio Interface components
194
- eis_file_input = gr.File(label="Upload EIS Data (CSV)")
195
- eis_analysis_output = gr.Textbox(label="EIS Analysis Summary", interactive=False)
196
- # Use Image component for plot files - Gradio will handle displaying the file from the path
197
- nyquist_plot_output = gr.Image(label="Nyquist Plot", type="filepath")
198
- bode_plots_output = gr.Image(label="Bode Plots", type="filepath")
199
- ai_query_input = gr.Textbox(label="Ask about Battery Materials or Recycling")
200
- ai_response_output = gr.Textbox(label="AI Research Assistant")
201
-
202
-
203
- # Create the integrated Gradio interface
204
- integrated_interface = gr.Interface(
205
- fn=process_eis_and_query_ai,
206
- inputs=[
207
- eis_file_input,
208
- ai_query_input
209
- ],
210
- outputs=[
211
- eis_analysis_output,
212
- nyquist_plot_output,
213
- bode_plots_output,
214
- ai_response_output
215
- ],
216
- title="🔋 VoltAIon - Integrated EIS Analysis and AI Chat",
217
- description="Upload EIS data (CSV with Frequency, Z_real, Z_imag) and ask the AI about battery materials, informed by the analysis."
218
  )
219
 
220
- # Launch the integrated interface
221
- # For deployment on Hugging Face Spaces, use launch(share=True) or simply launch()
222
- # Gradio handles the public URL for Spaces automatically.
223
  if __name__ == "__main__":
224
- integrated_interface.launch()
 
1
+ # app.py (Simplified for AI Chat Only)
2
  import gradio as gr
 
 
 
3
  import os
4
+ import requests
 
 
 
 
5
 
6
  # Assuming your API key is set as an environment variable in Hugging Face Spaces secrets
7
  API_KEY = os.getenv("AIML_API_KEY")
 
12
  return "API Key not set. Please set AIML_API_KEY environment variable."
13
  headers = {"Authorization": f"Bearer {API_KEY}"}
14
  data = {
15
+ "model": "openai/gpt-4o", # Or another model you have access to
16
  "messages": [
17
+ {"role": "system", "content": "You are an expert assistant for battery materials and sustainable energy."},
18
  {"role": "user", "content": user_input}
19
  ]
20
  }
 
33
  except Exception as e:
34
  return f"An error occurred during API query: {e}"
35
 
36
+ # Define Gradio Interface
37
+ ai_chat_interface = gr.Interface(
38
+ fn=query_gpt5,
39
+ inputs=gr.Textbox(label="Ask about Battery Materials or Sustainable Energy"),
40
+ outputs=gr.Textbox(label="AI Research Assistant"),
41
+ title="🤖 VoltAIon - AI Research Assistant (API Key Focus)",
42
+ description="Ask questions about battery materials and sustainable energy using the API."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  )
44
 
45
+ # Launch the interface
46
+ # For deployment on Hugging Face Spaces, use launch()
 
47
  if __name__ == "__main__":
48
+ ai_chat_interface.launch()