|
|
|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<title>File Upload</title> |
|
|
|
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"> |
|
|
|
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700" rel="stylesheet"> |
|
<link href="https://fonts.googleapis.com/css?family=Lora:400,700" rel="stylesheet"> |
|
|
|
<style> |
|
|
|
.card { |
|
opacity: 0; |
|
transition: opacity 0.5s ease-in-out; |
|
} |
|
|
|
.card.show { |
|
opacity: 1; |
|
} |
|
body { |
|
font-family: 'Lora', sans-serif; |
|
font-size: 16px; |
|
background-color: #eaf4ea; |
|
color: #333; |
|
} |
|
|
|
h1, h2, h3, h4, h5, h6 { |
|
font-family: 'Roboto', serif; |
|
font-weight: bold; |
|
} |
|
|
|
.container { |
|
background-color: rgba(255, 255, 255, 0.9); |
|
border-radius: 15px; |
|
padding: 20px; |
|
margin-top: 50px; |
|
} |
|
|
|
h1, h2 { |
|
color: #4CAF50; |
|
} |
|
|
|
button.btn-primary { |
|
background-color: #4CAF50; |
|
border: none; |
|
} |
|
|
|
button.btn-primary:hover { |
|
background-color: #45a049; |
|
} |
|
|
|
.card { |
|
background-color: #f8f9fa; |
|
border: 1px solid #ddd; |
|
border-radius: 10px; |
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); |
|
} |
|
|
|
.card-header { |
|
background-color: #4CAF50; |
|
color: white; |
|
border-radius: 10px 10px 0 0; |
|
} |
|
|
|
.card-body { |
|
padding: 15px; |
|
} |
|
|
|
.list-group-item { |
|
border: none; |
|
} |
|
|
|
.btn-success { |
|
background-color: #28a745; |
|
border: none; |
|
} |
|
|
|
.btn-success:hover { |
|
background-color: #218838; |
|
} |
|
|
|
#predictions:hover::before { |
|
content: "Tables displaying TPM values corresponding to plant tissues"; |
|
position: absolute; |
|
bottom: 100%; |
|
left: 50%; |
|
transform: translateX(-50%); |
|
background-color: #333; |
|
color: #fff; |
|
padding: 5px; |
|
border-radius: 5px; |
|
font-size: 12px; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="container"> |
|
<h1 class="mb-4"> |
|
<a href="https://huggingface.co/Gurveer05/FloraBERT" target="_blank" rel="noopener noreferrer" style="color: #218838;">FloraBERT</a> |
|
</h1> |
|
<form> |
|
<div class="form-group"> |
|
<label for="fileInput">Select .txt files:</label> |
|
<div class="input-group"> |
|
<div class="custom-file"> |
|
<input type="file" class="custom-file-input" id="fileInput" accept=".txt" multiple onchange="displaySelectedFiles()"> |
|
<label class="custom-file-label" for="fileInput">Choose files</label> |
|
</div> |
|
</div> |
|
</div> |
|
<button type="button" class="btn btn-primary" id="uploadButton" onclick="processFiles()">Upload and Process</button> |
|
<p id="uploadMessage" class="text-muted mt-2"></p> |
|
<div id="selectedFiles" class="mt-2"></div> |
|
</form> |
|
|
|
<h2 class="mt-5" id="predictions" title="Table displaying TPM values corresponding to plant tissues">Predictions</h2> |
|
<div id="loadingIcon" class="d-none"> |
|
<p class="text-muted">Processing... <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span></p> |
|
</div> |
|
<div id="predictionsList" class="mt-3"></div> |
|
|
|
<button type="button" class="btn btn-success mt-3" onclick="downloadAllPredictions()">Download All Predictions</button> |
|
</div> |
|
|
|
<script> |
|
|
|
const predictionsCache = {}; |
|
|
|
function displaySelectedFiles() { |
|
const fileInput = document.getElementById('fileInput'); |
|
const selectedFilesContainer = document.getElementById('selectedFiles'); |
|
const files = fileInput.files; |
|
|
|
selectedFilesContainer.innerHTML = ''; |
|
|
|
for (let i = 0; i < files.length; i++) { |
|
const fileName = files[i].name; |
|
const fileLabel = document.createElement('span'); |
|
fileLabel.innerText = fileName; |
|
|
|
if (i > 0) { |
|
selectedFilesContainer.appendChild(document.createTextNode(', ')); |
|
} |
|
|
|
selectedFilesContainer.appendChild(fileLabel); |
|
} |
|
} |
|
|
|
async function processFiles() { |
|
const fileInput = document.getElementById('fileInput'); |
|
const files = fileInput.files; |
|
|
|
const uploadButton = document.getElementById('uploadButton'); |
|
const uploadMessage = document.getElementById('uploadMessage'); |
|
const loadingIcon = document.getElementById('loadingIcon'); |
|
const predictionsList = document.getElementById('predictionsList'); |
|
const selectedFilesContainer = document.getElementById('selectedFiles'); |
|
|
|
|
|
uploadButton.disabled = true; |
|
|
|
uploadMessage.innerText = ''; |
|
|
|
if (files.length === 0) { |
|
|
|
uploadMessage.innerText = 'Please choose at least one file.'; |
|
|
|
uploadButton.disabled = false; |
|
return; |
|
} |
|
|
|
const url = 'http://127.0.0.1:8000'; |
|
|
|
loadingIcon.classList.remove('d-none'); |
|
|
|
|
|
for (let i = 0; i < files.length; i++) { |
|
const file = files[i]; |
|
const formData = new FormData(); |
|
formData.append('file', file); |
|
|
|
const response = await fetch(`${url}/uploadfile/`, { |
|
method: 'POST', |
|
body: formData |
|
}); |
|
|
|
if (response.ok) { |
|
const result = await response.json(); |
|
const filename = result.filename; |
|
|
|
const predictionsResponse = await fetch(`${url}/process/${filename}`); |
|
const predictions = await predictionsResponse.json(); |
|
|
|
predictionsCache[filename] = predictions; |
|
|
|
|
|
if (!document.getElementById(`card-${filename}`)) { |
|
const cardHtml = ` |
|
<div id="card-${filename}" class="card mt-3"> |
|
<div class="card-header"> |
|
${filename} |
|
</div> |
|
<div class="card-body"> |
|
<ul class="list-group list-group-flush"> |
|
${predictions.map((predictionList, index) => ` |
|
<li class="list-group-item"> |
|
<strong>Sequence ${index + 1}</strong> |
|
<table class="table table-bordered mt-2"> |
|
<thead> |
|
<tr> |
|
<th scope="col">Tissue</th> |
|
<th scope="col">Prediction</th> |
|
</tr> |
|
</thead> |
|
<tbody> |
|
${predictionList.map(prediction => ` |
|
<tr> |
|
<td>${prediction.tissue}</td> |
|
<td>${prediction.prediction}</td> |
|
</tr> |
|
`).join('')} |
|
</tbody> |
|
</table> |
|
</li> |
|
`).join('')} |
|
</ul> |
|
</div> |
|
</div> |
|
`; |
|
predictionsList.innerHTML = cardHtml + predictionsList.innerHTML; |
|
|
|
|
|
setTimeout(() => { |
|
document.querySelectorAll('.card').forEach(card => card.classList.add('show')); |
|
}, 100); |
|
} |
|
|
|
|
|
uploadMessage.innerText = `Processed files!`; |
|
|
|
|
|
setTimeout(() => { |
|
uploadMessage.innerText = ''; |
|
}, 2000); |
|
} else { |
|
console.error('Failed to upload file:', file.name); |
|
uploadMessage.innerText = `Failed to upload file ${i + 1} of ${files.length}.`; |
|
} |
|
} |
|
|
|
|
|
uploadButton.disabled = false; |
|
|
|
|
|
loadingIcon.classList.add('d-none'); |
|
|
|
|
|
selectedFilesContainer.innerHTML = ''; |
|
} |
|
|
|
function downloadAllPredictions() { |
|
|
|
const predictionsJSON = JSON.stringify(predictionsCache, null, 2); |
|
|
|
|
|
const blob = new Blob([predictionsJSON], { type: 'application/json' }); |
|
|
|
|
|
const a = document.createElement('a'); |
|
a.href = URL.createObjectURL(blob); |
|
a.download = 'all_predictions.json'; |
|
a.click(); |
|
} |
|
</script> |
|
|
|
|
|
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script> |
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script> |
|
</body> |
|
</html> |