517 lines
18 KiB
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>
|