open-organism-observer/create_report.html

789 lines
29 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<meta charset="utf-8">
<html>
<header>
<link href="bootstrap-5.0.2-dist/css/bootstrap.min.css" rel="stylesheet" ></link>
<script src="bootstrap-5.0.2-dist/js/bootstrap.bundle.min.js" ></script>
</header>
<body>
2025-02-25 18:11:42 +01:00
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo03" aria-controls="navbarTogglerDemo03" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="#">Open Microscopy App</a>
<div class="collapse navbar-collapse" id="navbarTogglerDemo03">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarScrollingDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Settings
</a>
<ul class="dropdown-menu" aria-labelledby="navbarScrollingDropdown">
<li><a class="dropdown-item" href="/setup_microscope.html">Setup Camera</a></li>
<li><a class="dropdown-item" href="/sample_prep_protocol.html">Setup Preparation Protocol</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Defaults</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/sample_intake.html">add sample</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarScrollingDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Observe
</a>
<ul class="dropdown-menu" aria-labelledby="navbarScrollingDropdown">
<li><a class="dropdown-item" href="/observe_nema.html">Nematodes</a></li>
<li><a class="dropdown-item" href="/observe_main.html">Filamentous and Protozoa</a></li>
<li><a class="dropdown-item" href="/observe_bact.html">Bacteria</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link" href="/create_report.html">generate report</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-3">
<label class = "form-label" for="sample_chooser">choose the sample</label>
<select class="form-select" name="sample_chooser" id = "sample_chooser"></select>
</div>
</div>
2025-01-29 15:43:14 +01:00
<h1> Report for Sample Number <span id = "sample_id">???</span></h1>
<p>
<span id = "sample_name">???</span> is a <span id = "sample_type">???</span>
sample taken on <span id="sample_date">???</span> at these coordinates
<span id = "sample_location">???</span>.
</p>
<div id = "main_scan_div">
<h2> Filamentous Organisms and Protozoa </h2>
<p id = "main_scan_text">
The main scan was performed on <span id = main_scan_datetime>???</span> using the
protocol <span id= "prep_protocol_name">???</span> and camera setup
<span id=cam_setup_name>???</span>.
</p>
<p>
Dividing the sample volume V<sub>Sample</sub> = <span id="sample_volume">???</span> uL
by the size of the coverslip A<sub>coverslip</sub> =
2025-01-29 15:43:14 +01:00
<span id="coverslip_height">???</span> mm x <span id="coverslip_width">???</span> mm
yields the observed height h<sub>observed</sub> = V<sub>Sample</sub> / A<sub>coverslip</sub> =
<span id="observed_height"></span> um. Multipilcation with the size of the the field of view
A<sub>FoV</sub> = <span id="FoV_height">???</span> um x
<span id="FoV_width">???</span> um
yields the observed Volume V<sub>observed</sub> =
h<sub>observed</sub> * A<sub>FoV</sub> = <span id="observed_volume">???</span> uL per FoV.
The volume of organisms per FoV is multiplied with the
dilution Factor F<sub>dilution</sub> = <span id="dilution_factor">???</span>
and devided by V<sub>observed</sub> to calculate the abundance per uL.
2025-01-29 15:43:14 +01:00
</p>
<p>
F<sub>multiplication</sub> = F<sub>dilution</sub> * 1 uL / V<sub>observed</sub> = <span id="factor">???</span>
</p>
2025-02-05 14:08:44 +01:00
<h3>Filamentous Organisms and Protozoa Table</h3>
2025-01-29 15:43:14 +01:00
<table class="table" id = "main_scan_table" style="width:100%">
<thead>
<tr>
<th>
2025-01-29 15:43:14 +01:00
organism
</th>
<th>
2025-02-05 14:08:44 +01:00
abundance [ug/uL] or [1/uL]
</th>
<th>
2025-01-29 15:43:14 +01:00
standard deviation [%]
</th>
</th>
</tr>
</thead>
2025-01-29 15:43:14 +01:00
<tbody>
</tbody>
</table>
2025-01-29 15:43:14 +01:00
</div>
2025-02-05 14:09:24 +01:00
<div id="bacteria_scan_div">
<h2> Bacteria Scan</h2>
<p>
The bacteria scan has been performed on <span id="bact_scan_datetime">???</span>.
Dividing the sample volume V<sub>Sample</sub> = <span id="sample_volume_bact">???</span> uL
by the size of the coverslip A<sub>coverslip</sub> =
2025-02-05 14:09:24 +01:00
<span id="coverslip_height_bact">???</span> mm x <span id="coverslip_width_bact">???</span> mm
yields the observed height h<sub>observed</sub> = V<sub>Sample</sub> / A<sub>coverslip</sub> =
<span id="observed_height_bact"></span> um. Multipilcation with the size of the
2025-02-05 14:09:24 +01:00
the field of view A<sub>FoV</sub> = <span id="FoV_height_bact">???</span> um x
<span id="FoV_width_bact">???</span> um yields the observed Volume
V<sub>observed</sub> = h<sub>observed</sub> * A<sub>FoV</sub> = <span id="observed_volume_bact">???</span> uL per FoV. The volume of organisms per FoV is multiplied with the
dilution Factor F<sub>dilution</sub> = <span id="dilution_factor_bact">???</span>
and devided by V<sub>observed</sub> to calculate the abundance per uL:
</p>
<p>
F<sub>multiplication</sub> = F<sub>dilution</sub> * 1 uL / V<sub>observed</sub> = <span id="factor_bact">???</span>
</p>
2025-02-05 14:09:24 +01:00
<h3> Bacteria Table </h3>
<table class="table" id = "bact_scan_table" style="width:100%">
<thead>
<tr>
<th>
type of Bacteria
</th>
<th>
count per FoV
</th>
<th>
area [um²] per FoV
</th>
<th>
number per uL +- [%]
</th>
<th>
~ ug / uL +- [%]
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<h3>Bacterial to Fungal Biomass </h3>
<p> The Bacterial m<sub>Bacteria</sub> = <span id="bacterial_biomass">???</span>
to Fungal Biomass m<sub>Fungi</sub> = <span id="fungal_biomass">???</span>.<br>
m<sub>Fungi</sub> / m<sub>Bacteria</sub> = <span id="f_to_b_biomass">???</span>
</p>
</div>
2025-01-29 15:43:14 +01:00
<div id="nematode_scan_div">
<h2> Nematode Scan </h2>
<p>
2025-02-05 14:09:24 +01:00
The namatode scan has been performed on <span id="nema_scan_datetime">???</span>
using the protocol <span id= "prep_protocol_name_bact">???</span> and camera setup
<span id=cam_setup_name_bact>???</span>. <br>
2025-01-29 15:43:14 +01:00
To calculate the abundance of nematodes per cubic centimeter of sample the dilution Factor F<sub>dilution</sub> =
<span id="dilution_nema">???</span> is divided by the sample size V<sub>sample</sub> =
<span id="samplesize_nema">???</span> uL. <br>
The multiplication factor for the nematode scan is: <br>
F<sub>nematode</sub> = F<sub>dilution</sub> / V<sub>sample</sub> = <span id="multiplication_factor_nema">???</span>
</p>
2025-02-05 14:09:24 +01:00
2025-01-29 15:43:14 +01:00
<h3> Nematode Table </h3>
<table class="table" id = "nema_scan_table" style="width:100%">
<thead>
<tr>
<th>
2025-01-29 15:43:14 +01:00
functional group
</th>
<th>
2025-01-29 15:43:14 +01:00
count
</th>
<th>
2025-01-29 15:43:14 +01:00
number per cm³
</th>
</tr>
</thead>
2025-01-29 15:43:14 +01:00
<tbody>
</tbody>
</table>
</div>
2025-01-29 15:43:14 +01:00
2025-02-05 14:09:24 +01:00
2025-01-29 15:43:14 +01:00
</div>
</body>
<script>
var sample;
var samples = {};
2025-01-29 15:43:14 +01:00
var main_scan_result
var prep_protocol;
var microscope_setup;
var multiplication_factor_main_scan;
var nema_scan_result
var prep_protocol_nema;
var microscope_setup_nema
var multiplication_factor_nema_scan;
var bact_scan_result;
var prep_protocol_bact;
var microscope_setup_bact;
var multiplication_factor_bact_scan;
var multiplication_factor_main_scan;
// open db
var db;
let openRequest = indexedDB.open("my_db");
openRequest.onerror = function() {
console.error("Error", openRequest.error);
};
openRequest.onsuccess = function() {
db = openRequest.result;
get_all_samples();
// continue working with database using db object
};
2025-01-29 15:43:14 +01:00
// first get all samples and make a sample chooser
function get_all_samples(){
const request = db.transaction('sample')
.objectStore('sample')
.openCursor();
request.onsuccess = ()=> {
let cursor = event.target.result;
if (cursor) {
// Access the current record
make_sample_chooser(cursor.value, cursor.key);
2025-01-29 15:43:14 +01:00
// Move to the next record
cursor.continue();
}
2025-01-29 15:43:14 +01:00
else{
sample = samples[sample_chooser.value];
write_sample_description(sample);
get_result_main(sample_chooser.value);
get_result_nema(sample_chooser.value);
2025-02-05 14:09:42 +01:00
get_result_bact(sample_chooser.value);
2025-01-29 15:43:14 +01:00
}
}
request.onerror = (err)=> {
console.error(`Error to get all setups: ${err}`)
}
}
var sample_chooser = document.querySelector("#sample_chooser");
function make_sample_chooser(sample, key){
let sampleID = document.createElement("option");
let text = document.createTextNode(sample.Name);
sampleID.value = key;
samples[key] = sample;
sampleID.appendChild(text);
sample_chooser.appendChild(sampleID);
}
sample_chooser.addEventListener("change", change_sample);
function change_sample(){
sample = samples[this.value];
2025-01-29 15:43:14 +01:00
write_sample_description(sample);
get_result_main(this.value);
get_result_nema(this.value);
2025-02-05 14:09:42 +01:00
get_result_bact(this.value);
2025-01-29 15:43:14 +01:00
};
2025-01-29 15:43:14 +01:00
function write_sample_description(sample){
let latLon = sample.Place.split(', ');
let lat = Number(latLon[0]);
let lon = Number(latLon[1]);
2025-01-29 15:43:14 +01:00
document.querySelector("#sample_id").textContent = sample_chooser.value;
document.querySelector("#sample_name").textContent = sample.Name;
document.querySelector("#sample_type").textContent = sample.Type;
document.querySelector("#sample_date").textContent = sample.Date_Collected.toDateString() + ' at ' + sample.Date_Collected.toLocaleTimeString();
document.querySelector("#sample_location").textContent = lat.toFixed(4) + ', ' + lon.toFixed(4);
2025-01-29 15:43:14 +01:00
}
function write_main_scan_description(main_result, prep_protocol, microscope_setup){
// observed height in um -> sample size [uL] * 10^9 / coverslip Area [mm²] * 10^6
// -> yields 1000 * samplesize[uL] / coverslipArea[mm²]
let observed_height = 1000 * Number(prep_protocol.Sample_Size) /
(Number(microscope_setup.Slip_Height) * Number(microscope_setup.Slip_Width));
// observed Volume in uL -> height [um] * FoV [um²] = um³ -- 1 um³ = 1* 10^-9 uL
let observed_volume = observed_height *
Number(microscope_setup.FoV_Width)*Number(microscope_setup.FoV_Height)*Math.pow(10, -9);
multiplication_factor_main_scan = main_result.dilution / observed_volume;
document.querySelector("#main_scan_datetime").textContent = main_result.datetime.toDateString() + ' at ' + main_result.datetime.toLocaleTimeString();
sample.Date_Collected.toDateString() + ' at ' + sample.Date_Collected.toLocaleTimeString();
2025-01-29 15:43:14 +01:00
document.querySelector("#prep_protocol_name").textContent = prep_protocol.name;
document.querySelector("#cam_setup_name").textContent = microscope_setup.name;
document.querySelector("#coverslip_height").textContent = microscope_setup.Slip_Height;
document.querySelector("#coverslip_width").textContent = microscope_setup.Slip_Width;
document.querySelector("#sample_volume").textContent = prep_protocol.Sample_Size;
document.querySelector("#observed_height").textContent = observed_height.toFixed(2);
document.querySelector("#FoV_height").textContent = microscope_setup.FoV_Height;
document.querySelector("#FoV_width").textContent = microscope_setup.FoV_Width;
document.querySelector("#observed_volume").textContent = observed_volume.toExponential(2);
document.querySelector("#dilution_factor").textContent = main_result.dilution;
document.querySelector("#factor").textContent = multiplication_factor_main_scan.toFixed(2);
2025-01-29 15:43:14 +01:00
}
// get results of the main scan + prep_protocol and microscope_setup
function get_result_main(sampleID){
const transaction = db.transaction('main_scan');
const objStore = transaction.objectStore('main_scan')
const index = objStore.index("sampleID");
const get_request = index.get(sampleID);
get_request.onsuccess = () => {
get_prep_protocol(get_request.result);
get_microscope_setup(get_request.result);
main_scan_result = get_request.result;
}
get_request.onerror = (err)=> {
console.error(`Error to get all setups: ${err}`)
}
}
function get_prep_protocol(result_obj){
const request = db.transaction('prep_protocol')
.objectStore('prep_protocol')
.get(Number(result_obj.prepID));
request.onsuccess = () => {
prep_protocol = request.result;
if (microscope_setup && prep_protocol && main_scan_result){
write_main_scan_description(main_scan_result, prep_protocol, microscope_setup);
render_main_scan_table(main_scan_result.result);
}
}
request.onerror = (err)=> {
console.error(`Error to get all setups: ${err}`)
}
}
function get_microscope_setup(result_obj){
console.log(result_obj);
const request = db.transaction('microscope_setup')
.objectStore('microscope_setup')
.get(Number(result_obj.setupID));
request.onsuccess = () => {
microscope_setup = request.result;
if (microscope_setup && prep_protocol && main_scan_result){
write_main_scan_description(main_scan_result, prep_protocol, microscope_setup);
render_main_scan_table(main_scan_result.result);
}
}
request.onerror = (err)=> {
console.error(`Error to get all setups: ${err}`)
}
}
function total_organisms_in_FoV(FoV){
var total = {
"Fungi" : 0.0,
"Oomycete" : 0.0,
"Actinobacteria" : 0.0,
"Flagelate" : 0.0,
"Ciliate" : 0.0,
"Amoeba" : 0.0,
}
FoV.forEach((item, i) => {
var all_organisms_in_picture = total_organisms(item.organisms);
var keys = Object.keys(all_organisms_in_picture);
for (let i = 0; i < keys.length; ++i) {
total[keys[i]] += all_organisms_in_picture[keys[i]];
}
2025-01-29 15:43:14 +01:00
});
return total;
}
function total_organisms(organisms){
var total = {
"Fungi" : 0.0,
"Oomycete" : 0.0,
"Actinobacteria" : 0.0,
"Flagelate" : 0.0,
"Ciliate" : 0.0,
"Amoeba" : 0.0,
}
organisms.forEach((item, i) => {
switch (item.type){
case "Fungi":
// calculate the Volume of filamentous organisms
total.Fungi += item.length*Number(microscope_setup.FoV_Width)*
Math.pow((item.width*Number(microscope_setup.FoV_Width)),2.0)*Math.PI/4.0;
break
case "Oomycete":
total.Oomycete += item.length*Number(microscope_setup.FoV_Width)*
Math.pow((item.width*Number(microscope_setup.FoV_Width)),2.0)*Math.PI/4.0;
break
case "Actinobacteria":
2025-02-05 14:09:42 +01:00
total.Actinobacteria += item.length*Number(microscope_setup.FoV_Width)*Math.PI/4.0;
2025-01-29 15:43:14 +01:00
break
case "Flagelate":
total.Flagelate +=1;
break
case "Ciliate":
total.Ciliate +=1;
break
case "Amoeba":
total.Amoeba +=1;
break
}
});
return total;
}
function get_standard_deviation(reading){
var total = {
"Fungi" : 0.0,
"Oomycete" : 0.0,
"Actinobacteria" : 0.0,
"Flagelate" : 0.0,
"Ciliate" : 0.0,
"Amoeba" : 0.0,
}
reading.forEach((item, index) => {
var all_organisms_in_FoV = total_organisms_in_FoV(item);
var keys = Object.keys(all_organisms_in_FoV);
for (let i = 0; i < keys.length; ++i) {
total[keys[i]] += all_organisms_in_FoV[keys[i]];
}
});
var mean = {};
var standard_deviation = {};
var keys = Object.keys(total);
for (var i = 0; i < keys.length; ++i) {
mean[keys[i]] = total[keys[i]]/reading.length;
standard_deviation[keys[i]] = 0;
}
reading.forEach((item, index) => {
var all_organisms_in_FoV = total_organisms_in_FoV(item);
var keys = Object.keys(all_organisms_in_FoV);
for (var i = 0; i < keys.length; ++i) {
standard_deviation[keys[i]] += Math.pow(all_organisms_in_FoV[keys[i]]-mean[keys[i]], 2);
}
});
for (var i = 0; i < keys.length; ++i) {
standard_deviation[keys[i]] = Math.sqrt(standard_deviation[keys[i]]/reading.length);
}
return {"mean" : mean, "standard_deviation" : standard_deviation};
}
var result_table = document.querySelector("#main_scan_table");
function render_main_scan_table(result){
// combine all readings into one dataset
combined_set = [];
result.forEach((item, i) => {
item.forEach((item2, j) => {
combined_set.push(item2);
});
});
let res = get_standard_deviation(combined_set);
console.log(res);
for (key in res.mean){
render_main_scan_table_row(key, res.mean[key], res.standard_deviation[key])
}
}
function render_main_scan_table_row(key, mean, stdev){
let newRow = result_table.children[1].insertRow();
switch(key){
case "Fungi":
case "Oomycete":
case "Actinobacteria":
newRow.insertCell(0).innerHTML = key ;
// get
newRow.insertCell(1).innerHTML = (mean * Math.pow(10, -6) * multiplication_factor_main_scan).toFixed(2);
newRow.insertCell(2).innerHTML = (stdev/mean * 100).toFixed(2);
2025-01-29 15:43:14 +01:00
break
default:
newRow.insertCell(0).innerHTML = key;
newRow.insertCell(1).innerHTML = (mean * multiplication_factor_main_scan).toFixed(2);
newRow.insertCell(2).innerHTML = (stdev/mean * 100).toFixed(2);
2025-01-29 15:43:14 +01:00
}
}
// Nematodes
function get_result_nema(sampleID){
const transaction = db.transaction('nematode_scan');
const objStore = transaction.objectStore('nematode_scan')
const index = objStore.index("sampleID");
const get_request = index.get(sampleID);
get_request.onsuccess = () => {
console.log(get_request.result);
get_prep_protocol_nema(get_request.result);
get_microscope_setup_nema(get_request.result);
nema_scan_result = get_request.result;
}
get_request.onerror = (err)=> {
console.error(`Error to get all setups: ${err}`)
}
}
function get_prep_protocol_nema(result_obj){
const request = db.transaction('prep_protocol')
.objectStore('prep_protocol')
.get(Number(result_obj.prepID));
request.onsuccess = () => {
prep_protocol_nema = request.result;
if (microscope_setup_nema && prep_protocol_nema && nema_scan_result){
write_nema_scan_description(main_scan_result, prep_protocol_nema, microscope_setup_nema);
render_nema_scan_table(nema_scan_result.result);
}
}
request.onerror = (err)=> {
console.error(`Error to get all setups: ${err}`)
}
}
2025-01-29 15:43:14 +01:00
function get_microscope_setup_nema(result_obj){
console.log(result_obj);
const request = db.transaction('microscope_setup')
.objectStore('microscope_setup')
.get(Number(result_obj.setupID));
request.onsuccess = () => {
microscope_setup = request.result;
if (microscope_setup && prep_protocol && main_scan_result){
write_nema_scan_description(main_scan_result, prep_protocol, microscope_setup);
render_nema_scan_table(nema_scan_result.nematodes);
}
}
request.onerror = (err)=> {
console.error(`Error to get all setups: ${err}`)
}
}
function write_nema_scan_description(result, protocol, setup){
multiplication_factor_nema_scan = (result.dilution / protocol.Sample_Size) * Math.pow(10,3);
document.querySelector("#nema_scan_datetime").innerHTML = result.datetime.toDateString() + ' at ' + result.datetime.toLocaleTimeString();
2025-01-29 15:43:14 +01:00
document.querySelector("#dilution_nema").innerHTML = result.dilution;
document.querySelector("#samplesize_nema").innerHTML = protocol.Sample_Size;
document.querySelector("#multiplication_factor_nema").innerHTML = multiplication_factor_nema_scan;
}
var nema_table = document.querySelector("#nema_scan_table");
function render_nema_scan_table(result){
let nema_count = {
"Fungal_Feeding" : 0,
"Bacterial_Feeding" : 0,
"Root_Feeding" : 0,
"Predatory" : 0,
}
for (let i = 0; i < result.length; i++){
nema_count[result[i].type] +=1;
}
for (key in nema_count){
render_nema_scan_table_row(key, nema_count[key]);
}
}
function render_nema_scan_table_row(key, count){
let newRow = nema_table.children[1].insertRow();
newRow.insertCell(0).innerHTML = key;
newRow.insertCell(1).innerHTML = count;
newRow.insertCell(2).innerHTML = count * multiplication_factor_nema_scan;
}
2025-02-05 14:09:42 +01:00
// bacteria
function get_result_bact(sampleID){
const transaction = db.transaction('bacterial_scan');
const objStore = transaction.objectStore('bacterial_scan')
const index = objStore.index("sampleID");
const get_request = index.get(sampleID);
get_request.onsuccess = () => {
bact_scan_result = get_request.result;
get_prep_protocol_bact(get_request.result);
get_microscope_setup_bact(get_request.result);
}
get_request.onerror = (err)=> {
console.error(`Error to get all setups: ${err}`)
}
}
function get_prep_protocol_bact(result_obj){
const request = db.transaction('prep_protocol')
.objectStore('prep_protocol')
.get(Number(result_obj.prepID));
request.onsuccess = () => {
prep_protocol_bact = request.result;
if (microscope_setup_bact && prep_protocol_bact && bact_scan_result){
write_bact_scan_description(bact_scan_result, prep_protocol_bact, microscope_setup_bact);
render_bact_scan_table(bact_scan_result);
}
}
request.onerror = (err)=> {
console.error(`Error to get all setups: ${err}`)
}
}
function get_microscope_setup_bact(result_obj){
const request = db.transaction('microscope_setup')
.objectStore('microscope_setup')
.get(Number(result_obj.setupID));
request.onsuccess = () => {
microscope_setup_bact = request.result;
if (microscope_setup_bact && prep_protocol_bact && bact_scan_result){
write_bact_scan_description(bact_scan_result, prep_protocol_bact, microscope_setup_bact);
render_bact_scan_table(bact_scan_result.result);
}
}
request.onerror = (err)=> {
console.error(`Error to get all setups: ${err}`)
}
}
function write_bact_scan_description(result, protocol, setup){
console.log('hi from writer')
// observed height in um -> sample size [uL] * 10^9 / coverslip Area [mm²] * 10^6
// -> yields 1000 * samplesize[uL] / coverslipArea[mm²]
let observed_height_bact = 1000 * Number(protocol.Sample_Size) /
(Number(setup.Slip_Height) * Number(setup.Slip_Width));
// observed Volume in uL -> height [um] * FoV [um²] = um³ -- 1 um³ = 1* 10^-9 uL
let observed_volume_bact = observed_height_bact *
Number(setup.FoV_Width)*Number(setup.FoV_Height)*Math.pow(10, -9);
multiplication_factor_bact_scan = result.dilution / observed_volume_bact;
document.querySelector("#bact_scan_datetime").textContent = result.datetime.toDateString() + " at " + result.datetime.toLocaleTimeString();
2025-02-05 14:09:42 +01:00
document.querySelector("#prep_protocol_name_bact").textContent = protocol.name;
document.querySelector("#cam_setup_name_bact").textContent = setup.name;
document.querySelector("#coverslip_height_bact").textContent = setup.Slip_Height;
document.querySelector("#coverslip_width_bact").textContent = setup.Slip_Width;
document.querySelector("#sample_volume_bact").textContent = prep_protocol.Sample_Size;
document.querySelector("#observed_height_bact").textContent = observed_height_bact.toFixed(2);
document.querySelector("#FoV_height_bact").textContent = microscope_setup.FoV_Height;
document.querySelector("#FoV_width_bact").textContent = microscope_setup.FoV_Width;
document.querySelector("#observed_volume_bact").textContent = observed_volume_bact.toExponential(2);
document.querySelector("#dilution_factor_bact").textContent = result.dilution;
document.querySelector("#factor_bact").textContent = multiplication_factor_bact_scan.toFixed(2);
2025-02-05 14:09:42 +01:00
}
var bact_table = document.querySelector("#bact_scan_table");
function render_bact_scan_table(result){
let counts = [];
if (result[0][0].length == 0){
for (let i=0; i<result.length; i++){
let res = result[i][1].slice(0, -1).map(Number);;
counts.push(res);
}
} else {
for (let i=0; i<result.length; i++){
counts.push(update_bact_count(result[i][0]));
}
}
console.log(counts);
means = [];
sds = [];
for (let i=0; i<counts[0].length; i++){
let sum = 0;
for (let j=0; j<counts.length; j++){
sum += counts[j][i];
}
means.push(sum/counts.length);
}
for (let i=0; i<counts[0].length; i++){
let sd = 0;
for (let j=0; j<counts.length; j++){
sd += Math.pow(means[i] - counts[j][i],2);
}
sd = Math.sqrt(sd/counts.length);
sds.push(sd);
}
console.log(means);
console.log(sds);
keys = [
'Bacilli','','Cocci','','Pathogenic',''
]
for (let i=0; i<means.length; i+=2){
render_bact_scan_table_row(keys[i], [means[i],means[i+1]], [sds[i],sds[i+1]]);
}
bact_mass = means[1] + means[3] + means[5];
2025-02-05 14:16:56 +01:00
fungi_mass = Number(result_table.children[1].children[0].children[1].innerHTML);
2025-02-05 18:13:56 +01:00
document.querySelector("#bacterial_biomass").textContent = bact_mass.toFixed(2)
document.querySelector("#fungal_biomass").textContent = fungi_mass.toFixed(2)
2025-02-05 14:16:56 +01:00
document.querySelector("#f_to_b_biomass").textContent = (fungi_mass / bact_mass).toFixed(5)
2025-02-05 14:09:42 +01:00
}
function render_bact_scan_table_row(key, mean, sd){
console.log(mean)
let newRow = bact_table.children[1].insertRow();
newRow.insertCell(0).innerHTML = key;
newRow.insertCell(1).innerHTML = mean[0] + " +/- " + sd[0];
newRow.insertCell(2).innerHTML = mean[1].toFixed(2) + " +/- " + sd[1].toFixed(2);
newRow.insertCell(3).innerHTML = (mean[0] * multiplication_factor_bact_scan).toFixed(2)
+ " +/- " + (100*(sd[0]/mean[0])).toFixed(2);
newRow.insertCell(4).innerHTML = (mean[1] * multiplication_factor_bact_scan*Math.pow(10,-6)).toExponential(2)
+ " +/- " + (100*(sd[1]/mean[1])).toFixed(2);
}
function update_bact_count(bacteria){
let bc = 0;
let cc = 0;
let pc = 0;
let abc = 0;
let acc = 0;
let apc = 0;
bacteria.forEach(function (item, index) {
switch(item[1]){
case "Bacteria":
bc += 1
abc += item[2];
break;
case "Cocci":
cc += 1
acc += item[2];
break;
case "Vibrio":
case "Spirilla":
case "Spirochetes":
pc += 1
apc += item[2];
break;
}
});
return [bc, abc, cc, acc, pc, apc];
}
</script>
</html>