open-organism-observer/create_report.html

517 lines
18 KiB
HTML

<!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>
<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>
<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>
The sample volume V<sub>Sample</sub> = <span id="sample_volume">???</span> uL
divided by the size of the coverslip A<sub>coverslip</sub> =
<span id="coverslip_height">???</span> mm x <span id="coverslip_width">???</span> mm
yield an observed height of
<br><br>
h<sub>observed</sub> = V<sub>Sample</sub> / A<sub>coverslip</sub> =
<span id="observed_height"></span> um.
<br><br>
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 yield
an observed Volume of
<br><br>
V<sub>observed</sub> = h<sub>observed</sub> * A<sub>FoV</sub> = <span id="observed_volume">???</span> uL per FoV.
</p>
<p>
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.<br>
F<sub>multiplication</sub> = F<sub>dilution</sub> * 1 uL / V<sub>observed</sub> = <span id="factor">???</span>
</p>
<h3>Filamentous Organisms and Protozoa Table</h3>
<table class="table" id = "main_scan_table" style="width:100%">
<thead>
<tr>
<th>
organism
</th>
<th>
abundance [ug/uL] or [1/uL]
</th>
<th>
standard deviation [%]
</th>
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<div id="nematode_scan_div">
<h2> Nematode Scan </h2>
<p>
The namatode scan has been performed on <span id="nema_scan_datetime">???</span>. <br>
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>
<h3> Nematode Table </h3>
<table class="table" id = "nema_scan_table" style="width:100%">
<thead>
<tr>
<th>
functional group
</th>
<th>
count
</th>
<th>
number per cm³
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</body>
<script>
var sample;
var samples = {};
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
};
// 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);
// Move to the next record
cursor.continue();
}
else{
sample = samples[sample_chooser.value];
write_sample_description(sample);
get_result_main(sample_chooser.value);
get_result_nema(sample_chooser.value);
}
}
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];
write_sample_description(sample);
get_result_main(this.value);
get_result_nema(this.value);
};
function write_sample_description(sample){
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;
document.querySelector("#sample_location").textContent = sample.Place;
}
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;
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;
}
// 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]];
}
});
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":
total.Actinobacteria += item.length*Number(microscope_setup.FoV_Width);
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).toExponential(2);
newRow.insertCell(2).innerHTML = (stdev/mean * 100);
break
default:
newRow.insertCell(0).innerHTML = key;
newRow.insertCell(1).innerHTML = mean * multiplication_factor_main_scan;
newRow.insertCell(2).innerHTML = (stdev/mean * 100);
}
}
// 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}`)
}
}
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;
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){
console.log("hi from nema table generator");
console.log(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;
}
</script>
</html>