MohammedSameerSyed commited on
Commit
e124dfb
Β·
verified Β·
1 Parent(s): de54158

Upload folder using huggingface_hub

Browse files
Files changed (4) hide show
  1. README.md +37 -7
  2. app.py +186 -0
  3. best_model.pth +3 -0
  4. requirements.txt +9 -0
README.md CHANGED
@@ -1,13 +1,43 @@
1
  ---
2
- title: Soho Comet Detector
3
- emoji: πŸ‘€
4
- colorFrom: yellow
5
- colorTo: pink
6
  sdk: gradio
7
- sdk_version: 5.49.0
8
  app_file: app.py
9
  pinned: false
10
- license: mit
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: SOHO Comet Detector
3
+ emoji: 🌟
4
+ colorFrom: blue
5
+ colorTo: purple
6
  sdk: gradio
7
+ sdk_version: 4.44.0
8
  app_file: app.py
9
  pinned: false
 
10
  ---
11
 
12
+ # 🌟 AI-Powered SOHO Comet Detector
13
+
14
+ Automatically detect comets in NASA's SOHO/LASCO coronagraph images using deep learning.
15
+
16
+ ## πŸš€ Features
17
+ - **99% Accuracy** on validation data
18
+ - **Difference Imaging** to highlight moving objects
19
+ - **EfficientNet-B0** classifier
20
+ - Real-time detection on uploaded image sequences
21
+
22
+ ## πŸ“Š Model Details
23
+ - **Architecture:** EfficientNet-B0
24
+ - **Training Data:** 1,590 patches (590 comet, 1,000 background)
25
+ - **Method:** Difference imaging + binary classification
26
+ - **Performance:** 99% precision, 99% recall
27
+
28
+ ## 🎯 Usage
29
+ 1. Upload a ZIP containing SOHO LASCO C3 FITS images
30
+ 2. Adjust confidence threshold (0.90 recommended)
31
+ 3. Click "Detect Comets"
32
+ 4. View results with detection confidence scores
33
+
34
+ ## πŸ“š Dataset
35
+ Trained on SOHO/LASCO C3 coronagraph data from the Sungrazer Project.
36
+
37
+ ## πŸ‘₯ Team
38
+ Sambhavi
39
+ Emily
40
+ Mohammed
41
+
42
+ ---
43
+ *Built with Gradio β€’ Powered by Hugging Face*
app.py ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import numpy as np
4
+ from astropy.io import fits
5
+ import timm
6
+ from torchvision import transforms
7
+ from PIL import Image
8
+ import matplotlib.pyplot as plt
9
+ from scipy.ndimage import zoom
10
+ from skimage.feature import peak_local_max
11
+ import zipfile
12
+ import tempfile
13
+ from pathlib import Path
14
+
15
+ class CometDetectorApp:
16
+ def __init__(self, model_path='best_model.pth'):
17
+ self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
18
+
19
+ self.model = timm.create_model('efficientnet_b0', pretrained=False, num_classes=2)
20
+ self.model.load_state_dict(torch.load(model_path, map_location=self.device))
21
+ self.model.to(self.device)
22
+ self.model.eval()
23
+
24
+ self.transform = transforms.Compose([
25
+ transforms.Resize((224, 224)),
26
+ transforms.ToTensor(),
27
+ transforms.Normalize(mean=[0.485, 0.456, 0.406],
28
+ std=[0.229, 0.224, 0.225])
29
+ ])
30
+
31
+ def load_fits_from_zip(self, zip_file):
32
+ images = []
33
+ filenames = []
34
+
35
+ with tempfile.TemporaryDirectory() as tmpdir:
36
+ with zipfile.ZipFile(zip_file, 'r') as zip_ref:
37
+ zip_ref.extractall(tmpdir)
38
+
39
+ fits_files = sorted(Path(tmpdir).rglob('*.fts')) + sorted(Path(tmpdir).rglob('*.fits'))
40
+
41
+ for fpath in fits_files:
42
+ try:
43
+ with fits.open(fpath) as hdul:
44
+ img = hdul[0].data.astype(np.float32)
45
+ if img.shape != (1024, 1024):
46
+ factor = 1024 / img.shape[0]
47
+ img = zoom(img, factor, order=1)
48
+ images.append(img)
49
+ filenames.append(fpath.name)
50
+ except:
51
+ continue
52
+
53
+ return np.array(images), filenames
54
+
55
+ def create_difference_images(self, images):
56
+ diff_images = []
57
+ for i in range(len(images) - 1):
58
+ diff = images[i+1] - images[i]
59
+ diff_images.append(diff)
60
+ max_proj = np.max(np.abs(np.array(diff_images)), axis=0)
61
+ return diff_images, max_proj
62
+
63
+ def detect_candidates(self, max_proj, threshold_percentile=95):
64
+ threshold = np.percentile(max_proj, threshold_percentile)
65
+ candidates = peak_local_max(max_proj, min_distance=20, threshold_abs=threshold)
66
+ return candidates
67
+
68
+ def extract_patch(self, image, center, patch_size=64):
69
+ y, x = center
70
+ half = patch_size // 2
71
+
72
+ y_start = max(0, y - half)
73
+ y_end = min(image.shape[0], y + half)
74
+ x_start = max(0, x - half)
75
+ x_end = min(image.shape[1], x + half)
76
+
77
+ patch = image[y_start:y_end, x_start:x_end]
78
+
79
+ if patch.shape != (patch_size, patch_size):
80
+ padded = np.zeros((patch_size, patch_size))
81
+ padded[:patch.shape[0], :patch.shape[1]] = patch
82
+ patch = padded
83
+
84
+ return patch
85
+
86
+ def classify_patch(self, patch):
87
+ patch_norm = (patch - patch.min()) / (patch.max() - patch.min() + 1e-8)
88
+ patch_rgb = np.stack([patch_norm]*3, axis=-1)
89
+ patch_rgb = (patch_rgb * 255).astype(np.uint8)
90
+
91
+ patch_pil = Image.fromarray(patch_rgb)
92
+ patch_tensor = self.transform(patch_pil).unsqueeze(0).to(self.device)
93
+
94
+ with torch.no_grad():
95
+ output = self.model(patch_tensor)
96
+ probs = torch.softmax(output, dim=1)
97
+ pred_class = torch.argmax(probs, dim=1).item()
98
+ confidence = probs[0][pred_class].item()
99
+
100
+ return pred_class, confidence
101
+
102
+ def process_and_visualize(self, zip_file, confidence_threshold):
103
+ try:
104
+ images, filenames = self.load_fits_from_zip(zip_file.name)
105
+
106
+ if len(images) < 2:
107
+ return None, "❌ Need at least 2 FITS images in the zip file"
108
+
109
+ diff_images, max_proj = self.create_difference_images(images)
110
+ candidates = self.detect_candidates(max_proj)
111
+
112
+ detections = []
113
+ for y, x in candidates:
114
+ patch = self.extract_patch(max_proj, (y, x))
115
+ pred_class, confidence = self.classify_patch(patch)
116
+
117
+ if pred_class == 0 and confidence >= confidence_threshold:
118
+ detections.append({'position': (y, x), 'confidence': confidence})
119
+
120
+ fig, axes = plt.subplots(1, 2, figsize=(14, 6))
121
+
122
+ axes[0].imshow(images[0], cmap='gray')
123
+ axes[0].set_title('First Image in Sequence')
124
+ axes[0].axis('off')
125
+
126
+ axes[1].imshow(max_proj, cmap='hot')
127
+ axes[1].set_title(f'Comet Detection Results')
128
+
129
+ for det in detections:
130
+ y, x = det['position']
131
+ axes[1].plot(x, y, 'g*', markersize=20, markeredgecolor='lime', markeredgewidth=2)
132
+ axes[1].text(x+15, y-15, f"{det['confidence']:.2f}",
133
+ color='lime', fontsize=12, weight='bold',
134
+ bbox=dict(boxstyle='round', facecolor='black', alpha=0.7))
135
+
136
+ axes[1].axis('off')
137
+ plt.tight_layout()
138
+
139
+ if len(detections) > 0:
140
+ summary = f"βœ… **{len(detections)} COMET(S) DETECTED!**\n\n"
141
+ for i, det in enumerate(detections, 1):
142
+ y, x = det['position']
143
+ summary += f"**Comet #{i}:**\n- Position: ({y}, {x})\n- Confidence: {det['confidence']:.1%}\n\n"
144
+ else:
145
+ summary = "❌ No comets detected in this sequence.\n\n"
146
+
147
+ summary += f"**Processing Info:**\n- Images analyzed: {len(images)}\n- Candidates examined: {len(candidates)}\n- Confidence threshold: {confidence_threshold:.1%}"
148
+
149
+ return fig, summary
150
+
151
+ except Exception as e:
152
+ return None, f"❌ Error processing images: {str(e)}"
153
+
154
+ detector = CometDetectorApp('best_model.pth')
155
+
156
+ with gr.Blocks(theme=gr.themes.Soft(), title="SOHO Comet Detector") as demo:
157
+ gr.Markdown("""
158
+ # 🌟 AI-Powered SOHO Comet Detector
159
+
160
+ Upload a **ZIP file** containing SOHO/LASCO C3 FITS images from a time sequence.
161
+ The AI will automatically detect comets using difference imaging and deep learning.
162
+
163
+ ### πŸ“ How to prepare your data:
164
+ 1. Download SOHO LASCO C3 images (6-hour sequence)
165
+ 2. Put all .fts or .fits files in a folder
166
+ 3. Zip the folder and upload here
167
+
168
+ ### πŸ”¬ Model: EfficientNet-B0 | Accuracy: 99%
169
+ """)
170
+
171
+ with gr.Row():
172
+ with gr.Column():
173
+ zip_input = gr.File(label="Upload ZIP of FITS Images", file_types=[".zip"], type="filepath")
174
+ confidence_slider = gr.Slider(minimum=0.5, maximum=0.99, value=0.90, step=0.05,
175
+ label="Confidence Threshold", info="Higher = fewer false positives")
176
+ detect_button = gr.Button("πŸ” Detect Comets", variant="primary", size="lg")
177
+
178
+ with gr.Column():
179
+ output_plot = gr.Plot(label="Detection Results")
180
+ output_text = gr.Markdown(label="Summary")
181
+
182
+ detect_button.click(fn=detector.process_and_visualize, inputs=[zip_input, confidence_slider],
183
+ outputs=[output_plot, output_text])
184
+
185
+ if __name__ == "__main__":
186
+ demo.launch()
best_model.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e21c528b5ba532d474414c4f3773d0359cf15a3dd17577b9cad2e937d05e8a93
3
+ size 16336121
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ gradio>=4.0.0
2
+ torch>=2.0.0
3
+ timm>=0.9.0
4
+ astropy>=5.0.0
5
+ scikit-image>=0.21.0
6
+ numpy>=1.24.0
7
+ matplotlib>=3.7.0
8
+ scipy>=1.11.0
9
+ Pillow>=10.0.0