train-modle / static /js /medical-datasets.js
fokan's picture
Force Space rebuild v2.1.0 with incremental training
cca1fa9
/**
* Medical Datasets Manager JavaScript
* Handles medical datasets functionality
*/
class MedicalDatasetsManager {
constructor() {
this.datasets = [];
this.loadedDatasets = new Set();
this.systemInfo = {};
this.init();
}
init() {
this.loadDatasets();
this.loadSystemInfo();
this.setupEventListeners();
this.setupDatabaseManagement();
// Refresh system info every 30 seconds
setInterval(() => this.loadSystemInfo(), 30000);
}
setupEventListeners() {
// Dataset loading modal events
document.getElementById('load-dataset-btn').addEventListener('click', () => {
this.loadSelectedDataset();
});
}
async loadDatasets() {
try {
const response = await fetch('/api/medical-datasets');
const data = await response.json();
if (response.ok) {
this.datasets = data.datasets;
this.renderDatasets();
} else {
this.showError('فشل في تحميل قواعد البيانات');
}
} catch (error) {
console.error('Error loading datasets:', error);
this.showError('خطأ في الاتصال بالخادم');
}
}
async loadSystemInfo() {
try {
const response = await fetch('/api/system/performance');
const data = await response.json();
if (response.ok) {
this.systemInfo = data;
this.updateSystemInfo();
}
} catch (error) {
console.error('Error loading system info:', error);
}
}
updateSystemInfo() {
const memoryElement = document.getElementById('memory-usage');
const cpuElement = document.getElementById('cpu-cores');
const datasetsElement = document.getElementById('loaded-datasets');
const tokenElement = document.getElementById('active-token');
if (this.systemInfo.memory) {
const memoryPercent = this.systemInfo.memory.process_memory_percent || 0;
memoryElement.textContent = `${memoryPercent.toFixed(1)}%`;
// Update color based on usage
memoryElement.className = memoryPercent > 80 ? 'h5 text-danger' :
memoryPercent > 60 ? 'h5 text-warning' : 'h5 text-primary';
}
if (this.systemInfo.cpu_cores) {
cpuElement.textContent = `${this.systemInfo.cpu_cores} نواة`;
}
datasetsElement.textContent = this.loadedDatasets.size;
// Update token information
this.updateTokenInfo();
}
async updateTokenInfo() {
try {
const response = await fetch('/api/tokens/for-task/medical');
if (response.ok) {
const data = await response.json();
const tokenElement = document.getElementById('active-token');
if (data.success) {
tokenElement.textContent = data.token_info.type_name;
tokenElement.className = 'h6 text-success';
tokenElement.title = `${data.token_info.description} - مستوى الأمان: ${data.token_info.security_level}`;
} else {
tokenElement.textContent = 'غير متوفر';
tokenElement.className = 'h6 text-danger';
}
}
} catch (error) {
console.error('Error getting token info:', error);
const tokenElement = document.getElementById('active-token');
tokenElement.textContent = 'خطأ';
tokenElement.className = 'h6 text-warning';
}
}
renderDatasets() {
const container = document.getElementById('datasets-grid');
if (this.datasets.length === 0) {
container.innerHTML = `
<div class="col-12 text-center text-muted py-5">
<i class="fas fa-database fa-4x mb-3"></i>
<h4>لا توجد قواعد بيانات متاحة</h4>
<p>تحقق من الاتصال بالإنترنت أو إعدادات الرموز المميزة</p>
</div>
`;
return;
}
const datasetsHtml = this.datasets.map(dataset => this.renderDatasetCard(dataset)).join('');
container.innerHTML = `<div class="row">${datasetsHtml}</div>`;
}
renderDatasetCard(dataset) {
const modalitiesBadges = dataset.modalities.map(modality =>
`<span class="modality-badge badge bg-primary">${this.getModalityText(modality)}</span>`
).join('');
const specialtiesBadges = dataset.medical_specialties.map(specialty =>
`<span class="specialty-badge">${this.getSpecialtyText(specialty)}</span>`
).join('');
const languageFlags = dataset.languages.map(lang =>
`<span class="badge bg-secondary me-1">${this.getLanguageText(lang)}</span>`
).join('');
const isLoaded = this.loadedDatasets.has(dataset.key);
const statusClass = isLoaded ? 'status-loaded' : 'status-available';
const statusText = isLoaded ? 'محمل' : 'متاح';
return `
<div class="col-lg-6 col-xl-4">
<div class="dataset-card position-relative">
<div class="dataset-status ${statusClass}">${statusText}</div>
<div class="text-center">
<i class="fas ${this.getDatasetIcon(dataset.modalities)} medical-icon"></i>
<h5 class="mb-2">${dataset.name}</h5>
<p class="text-muted mb-3">${dataset.description}</p>
</div>
<div class="mb-3">
<div class="d-flex justify-content-between align-items-center mb-2">
<span class="size-indicator">
<i class="fas fa-hdd me-1"></i>
${dataset.size_gb} جيجابايت
</span>
<span class="samples-indicator">
<i class="fas fa-images me-1"></i>
${this.formatNumber(dataset.num_samples)} عينة
</span>
</div>
</div>
<div class="mb-3">
<h6 class="mb-2">الوسائط:</h6>
<div>${modalitiesBadges}</div>
</div>
<div class="mb-3">
<h6 class="mb-2">التخصصات الطبية:</h6>
<div>${specialtiesBadges}</div>
</div>
<div class="mb-3">
<h6 class="mb-2">اللغات:</h6>
<div>${languageFlags}</div>
</div>
<div class="dataset-actions">
<button class="btn btn-outline-info btn-sm flex-fill"
onclick="medicalDatasets.showDatasetDetails('${dataset.key}')">
<i class="fas fa-info-circle me-1"></i>
التفاصيل
</button>
${!isLoaded ? `
<button class="btn btn-primary btn-sm flex-fill"
onclick="medicalDatasets.loadDataset('${dataset.key}')">
<i class="fas fa-download me-1"></i>
تحميل
</button>
` : `
<button class="btn btn-success btn-sm flex-fill" disabled>
<i class="fas fa-check me-1"></i>
محمل
</button>
`}
</div>
</div>
</div>
`;
}
getDatasetIcon(modalities) {
if (modalities.includes('radiology') || modalities.includes('ct_scan')) {
return 'fa-x-ray';
} else if (modalities.includes('multimodal')) {
return 'fa-layer-group';
} else if (modalities.includes('imaging')) {
return 'fa-image';
}
return 'fa-database';
}
getModalityText(modality) {
const modalityTexts = {
'radiology': 'أشعة',
'ct_scan': 'أشعة مقطعية',
'text': 'نص',
'multimodal': 'متعدد الوسائط',
'imaging': 'تصوير طبي',
'vision': 'رؤية حاسوبية'
};
return modalityTexts[modality] || modality;
}
getSpecialtyText(specialty) {
const specialtyTexts = {
'radiology': 'الأشعة',
'general': 'عام',
'emergency': 'طوارئ',
'internal_medicine': 'باطنة',
'cardiology': 'قلب',
'neurology': 'أعصاب',
'oncology': 'أورام'
};
return specialtyTexts[specialty] || specialty;
}
getLanguageText(language) {
const languageTexts = {
'en': 'إنجليزي',
'ar': 'عربي',
'fr': 'فرنسي'
};
return languageTexts[language] || language;
}
formatNumber(num) {
if (num >= 1000000) {
return (num / 1000000).toFixed(1) + 'م';
} else if (num >= 1000) {
return (num / 1000).toFixed(1) + 'ك';
}
return num.toString();
}
showDatasetDetails(datasetKey) {
const dataset = this.datasets.find(d => d.key === datasetKey);
if (!dataset) return;
document.getElementById('dataset-details-title').innerHTML =
`<i class="fas fa-info-circle me-2"></i>${dataset.name}`;
const detailsContent = `
<div class="row">
<div class="col-md-6">
<h6>معلومات أساسية</h6>
<table class="table table-sm">
<tr><td><strong>المعرف:</strong></td><td>${dataset.repo_id}</td></tr>
<tr><td><strong>الحجم:</strong></td><td>${dataset.size_gb} جيجابايت</td></tr>
<tr><td><strong>عدد العينات:</strong></td><td>${this.formatNumber(dataset.num_samples)}</td></tr>
<tr><td><strong>دعم التدفق:</strong></td><td>${dataset.streaming_supported ? 'نعم' : 'لا'}</td></tr>
</table>
</div>
<div class="col-md-6">
<h6>التفاصيل التقنية</h6>
<table class="table table-sm">
<tr><td><strong>تنسيق البيانات:</strong></td><td>${dataset.data_format}</td></tr>
<tr><td><strong>الوسائط:</strong></td><td>${dataset.modalities.join(', ')}</td></tr>
<tr><td><strong>التخصصات:</strong></td><td>${dataset.medical_specialties.join(', ')}</td></tr>
<tr><td><strong>اللغات:</strong></td><td>${dataset.languages.join(', ')}</td></tr>
</table>
</div>
</div>
<div class="mt-3">
<h6>الوصف</h6>
<p class="text-muted">${dataset.description}</p>
</div>
<div class="mt-3">
<h6>متطلبات النظام</h6>
<div class="alert alert-info">
<i class="fas fa-info-circle me-2"></i>
يتطلب هذا المجموعة ذاكرة تقديرية ${Math.ceil(dataset.size_gb * 1.5)} جيجابايت للمعالجة
</div>
</div>
`;
document.getElementById('dataset-details-content').innerHTML = detailsContent;
// Set up load button
const loadBtn = document.getElementById('load-dataset-btn');
loadBtn.onclick = () => this.loadDataset(datasetKey);
const modal = new bootstrap.Modal(document.getElementById('datasetDetailsModal'));
modal.show();
}
async loadDataset(datasetKey) {
const dataset = this.datasets.find(d => d.key === datasetKey);
if (!dataset) return;
// Close details modal if open
const detailsModal = bootstrap.Modal.getInstance(document.getElementById('datasetDetailsModal'));
if (detailsModal) {
detailsModal.hide();
}
// Show loading modal
document.getElementById('loading-dataset-name').textContent = dataset.name;
document.getElementById('loading-status').textContent = 'جاري تحضير التحميل...';
const loadingModal = new bootstrap.Modal(document.getElementById('loadingModal'));
loadingModal.show();
try {
const formData = new FormData();
formData.append('dataset_name', datasetKey);
formData.append('streaming', 'true');
formData.append('split', 'train');
document.getElementById('loading-status').textContent = 'جاري تحميل البيانات...';
const response = await fetch('/api/medical-datasets/load', {
method: 'POST',
body: formData
});
const data = await response.json();
if (response.ok) {
this.loadedDatasets.add(datasetKey);
this.renderDatasets();
this.updateSystemInfo();
loadingModal.hide();
this.showSuccess(`تم تحميل ${dataset.name} بنجاح`);
} else {
loadingModal.hide();
this.showError(data.detail || 'فشل في تحميل قاعدة البيانات');
}
} catch (error) {
console.error('Error loading dataset:', error);
loadingModal.hide();
this.showError('خطأ في الاتصال بالخادم');
}
}
async refreshDatasets() {
await this.loadDatasets();
await this.loadSystemInfo();
this.showSuccess('تم تحديث البيانات');
}
showSuccess(message) {
document.getElementById('success-message').textContent = message;
const toast = new bootstrap.Toast(document.getElementById('success-toast'));
toast.show();
}
showError(message) {
document.getElementById('error-message').textContent = message;
const toast = new bootstrap.Toast(document.getElementById('error-toast'));
toast.show();
}
setupDatabaseManagement() {
// Search datasets
const searchButton = document.getElementById('search-datasets');
if (searchButton) {
searchButton.addEventListener('click', () => {
this.searchDatabases();
});
}
// Search on Enter key
const searchQuery = document.getElementById('search-query');
if (searchQuery) {
searchQuery.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
this.searchDatabases();
}
});
}
// Add dataset form
const addForm = document.getElementById('add-dataset-form');
if (addForm) {
addForm.addEventListener('submit', (e) => {
e.preventDefault();
this.addDatabase();
});
}
// Validate dataset
const validateButton = document.getElementById('validate-dataset');
if (validateButton) {
validateButton.addEventListener('click', () => {
this.validateDataset();
});
}
// Refresh databases
const refreshButton = document.getElementById('refresh-databases');
if (refreshButton) {
refreshButton.addEventListener('click', () => {
this.loadConfiguredDatabases();
});
}
// Load configured databases on startup
this.loadConfiguredDatabases();
}
async searchDatabases() {
const queryElement = document.getElementById('search-query');
const categoryElement = document.getElementById('search-category');
if (!queryElement) return;
const query = queryElement.value.trim();
const category = categoryElement ? categoryElement.value : '';
if (!query) {
this.showError('يرجى إدخال كلمة البحث');
return;
}
const searchButton = document.getElementById('search-datasets');
const originalText = searchButton.innerHTML;
searchButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> جاري البحث...';
searchButton.disabled = true;
try {
const response = await fetch('/api/databases/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: query,
limit: 20,
category: category || null
})
});
const data = await response.json();
if (data.success) {
this.displaySearchResults(data.results);
} else {
this.showError('فشل في البحث عن قواعد البيانات');
}
} catch (error) {
console.error('Error searching databases:', error);
this.showError('خطأ في البحث عن قواعد البيانات');
} finally {
searchButton.innerHTML = originalText;
searchButton.disabled = false;
}
}
displaySearchResults(results) {
const resultsContainer = document.getElementById('search-results-list');
const searchResults = document.getElementById('search-results');
if (!resultsContainer || !searchResults) return;
if (results.length === 0) {
resultsContainer.innerHTML = '<p class="text-muted">لم يتم العثور على نتائج</p>';
} else {
resultsContainer.innerHTML = results.map(result => `
<div class="card mb-2">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start">
<div>
<h6 class="card-title">${result.name}</h6>
<p class="card-text text-muted small">${result.description || 'لا يوجد وصف'}</p>
<div class="d-flex gap-2">
<span class="badge bg-primary">${result.author}</span>
<span class="badge bg-secondary">${result.downloads || 0} تحميل</span>
<span class="badge bg-success">${result.likes || 0} إعجاب</span>
</div>
</div>
<button class="btn btn-sm btn-outline-primary" onclick="medicalDatasets.addDatabaseFromSearch('${result.id}', '${result.name}', '${result.description || ''}')">
<i class="fas fa-plus"></i> إضافة
</button>
</div>
</div>
</div>
`).join('');
}
searchResults.style.display = 'block';
}
async addDatabaseFromSearch(datasetId, name, description) {
try {
const databaseInfo = {
name: name,
dataset_id: datasetId,
category: 'medical',
description: description,
language: 'English',
modality: 'text'
};
const success = await this.submitDatabase(databaseInfo);
if (success) {
this.showSuccess(`تم إضافة قاعدة البيانات: ${name}`);
this.loadConfiguredDatabases();
}
} catch (error) {
console.error('Error adding database from search:', error);
this.showError('فشل في إضافة قاعدة البيانات');
}
}
async loadConfiguredDatabases() {
try {
const response = await fetch('/api/databases');
const data = await response.json();
if (data.success) {
this.displayConfiguredDatabases(data.databases, data.selected);
}
} catch (error) {
console.error('Error loading configured databases:', error);
}
}
displayConfiguredDatabases(databases, selected) {
const container = document.getElementById('configured-databases');
if (!container) return;
if (Object.keys(databases).length === 0) {
container.innerHTML = '<p class="text-muted">لا توجد قواعد بيانات مُعدة</p>';
return;
}
container.innerHTML = Object.entries(databases).map(([id, db]) => `
<div class="card mb-2">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start">
<div class="flex-grow-1">
<div class="form-check">
<input class="form-check-input" type="checkbox"
id="db-${id}" ${selected.includes(id) ? 'checked' : ''}
onchange="medicalDatasets.toggleDatabaseSelection('${id}', this.checked)">
<label class="form-check-label" for="db-${id}">
<h6 class="mb-1">${db.name}</h6>
</label>
</div>
<p class="text-muted small mb-1">${db.description || 'لا يوجد وصف'}</p>
<div class="d-flex gap-2">
<span class="badge bg-primary">${db.category}</span>
<span class="badge bg-secondary">${db.language}</span>
<span class="badge bg-info">${db.modality}</span>
</div>
</div>
<div class="d-flex gap-1">
<button class="btn btn-sm btn-outline-danger" onclick="medicalDatasets.removeDatabase('${id}')">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
</div>
`).join('');
}
async toggleDatabaseSelection(databaseId, selected) {
try {
if (selected) {
const response = await fetch('/api/databases/select', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
database_ids: [databaseId]
})
});
if (response.ok) {
this.showSuccess('تم تحديد قاعدة البيانات');
}
} else {
this.showInfo('تم إلغاء تحديد قاعدة البيانات');
}
} catch (error) {
console.error('Error toggling database selection:', error);
this.showError('فشل في تحديث اختيار قاعدة البيانات');
}
}
async removeDatabase(databaseId) {
if (!confirm('هل أنت متأكد من حذف قاعدة البيانات؟')) {
return;
}
try {
const response = await fetch(`/api/databases/${encodeURIComponent(databaseId)}`, {
method: 'DELETE'
});
const data = await response.json();
if (data.success) {
this.showSuccess('تم حذف قاعدة البيانات');
this.loadConfiguredDatabases();
} else {
this.showError('فشل في حذف قاعدة البيانات');
}
} catch (error) {
console.error('Error removing database:', error);
this.showError('خطأ في حذف قاعدة البيانات');
}
}
async submitDatabase(databaseInfo) {
try {
const response = await fetch('/api/databases/add', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(databaseInfo)
});
const data = await response.json();
return data.success;
} catch (error) {
console.error('Error submitting database:', error);
this.showError('فشل في إضافة قاعدة البيانات');
return false;
}
}
}
// Initialize medical datasets manager when page loads
document.addEventListener('DOMContentLoaded', () => {
window.medicalDatasets = new MedicalDatasetsManager();
});