diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 43b7a3c..82acf96 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -1,6 +1,8 @@ services: couchdb: - image: couchdb:3.1.1 + build: + context: .. + dockerfile: Dockerfile environment: - COUCHDB_USER=admin - COUCHDB_PASSWORD=secret @@ -9,6 +11,12 @@ services: - ../seed:/opt/couchdb/seed:ro ports: - "5984:5984" + healthcheck: + test: ["CMD", "curl", "-sf", "http://localhost:5984/_up"] + interval: 10s + timeout: 5s + retries: 10 + start_period: 15s networks: - statusdb-network @@ -20,7 +28,8 @@ services: networks: - statusdb-network depends_on: - - couchdb + couchdb: + condition: service_healthy volumes: couchdb-data: diff --git a/DATABASES.md b/DATABASES.md new file mode 100644 index 0000000..304af41 --- /dev/null +++ b/DATABASES.md @@ -0,0 +1,220 @@ +# Database Documentation + +This file documents the purpose and contents of each CouchDB database in the seed data. + +--- + +## `agreement_templates` + +Storing templates used to create user agreements. One document per template. Seems to be both versions (different documents) and editions (updates of document)? + +--- + +## `agreements` + +Stores user agreements created in Genomics Status, connected to the cost calculator implementation in Genoimcs Status. + +--- + +## DEPRECATED: `analysis` + +Summary statistics from various analysis, likely updated from `Piper` or similar since its not updated anymore. Likely stopped being updated around 2020 or similar. + +--- + +## `application_categories` + +Listing our application categories and abrevation, with one document per application. Used by the statistics api of genstat which in turn feeds the dashboard. + +--- + +## `bioinfo_analysis` + +Listing status flags for bioinfo tab on Genomics Status. One document per sample-flowcell-lane combination, which gets problematic when setting a status on flowcell level when there is a lot of samples on many lanes. +Documents are created by ngi-pipeline or TACA and statuses can be set from Genomics Status UI. + +--- + +## `biomek_logs` + +Short log messages from the biomek runs. + +--- + +## `charon` + +Huge database tracking sample status on the bioinfo side. Database for the Charon web application which has up to 2025 also been used by the Uppsala node of NGI. Lots of different types of documents with different content and structure. + +--- + +## `cost_calculator` + +Storing the prices for our different offerings. One document per version of the cost calculator. Updated from Genomics Status and used by Genomics Status to display cost and generate agreements. + +--- + +## `cronjobs` + +Storing the output of `crontab -l` for different users and servers, updated by TACA in a cronjob, and displayed on Genomics Status. One document per server, with different users appended to the document. + +--- + +## `element_runs` + +Flowcells database for the Element Bioisciences sequencing instrument. Created by TACA and displayed on Genomics Status. + +--- + +## DEPRECATED `expected_yields` + +One document per run mode and sequencer. Not sure where this is used. + +--- + +## DEPRECATED `flowcells` + +Illumina flowcells database used for pre HiSeq-X. Not updated after 2016. + +--- + +## `gs_configs` + +Miscelaneous config files used for genomics status. + +--- + +## `gs_links` + +Tracking the links added to projects on Genomics Status. One project link per document. + +--- + +## `gs_users` + +Genomics Status users, one document for each user. Keeps track of Initials, roles and user presets. + +--- + +## DEPRECATED `instrument_logs` + +Instrument logs very similar to the biomek_logs databse, but seems to have been used by the Bravo computers, last update was August 2025 but I think the Bravo computers were taken offline after that. + +--- + +## `instruments` + +Might be out of date, used by fc_trends plot to name the instruments. A database to list all sequencing instrument IDs and corresponding names. Can be replaced with a gs_config document. + +--- + +## `nanopore_runs` + +The flowcells database for ONT. One document per flowcell and run. A reused flowcell will generate a new document. + +--- + + +## `people_assignments` + +Keeps track of assignment of people to projects. Used in Genomics Status project cards and the project page introduced around 2025. + +--- + +## [DEPRECATED] `pricing_components` + +Was used for cost calculator on Genstat before it was actually launched. The information is now instead baked into cost_calculator documents. + +--- + +### `pricing_exchange_rates` + +Tracking exchange rates USD to SEK and EUR to SEK. Keeping a historical record so we can rewind time when changing agreements that was generated some time ago and we would like to keep the same exchange rate. One document per update, updated weekly by a cronjob. + +--- + +## [DEPRECATED] `pricing_products` + +Was used for cost calculator on Genstat before it was actually launched. The information is now instead baked into cost_calculator documents. + +--- + +## `projects` + +One of the major databases that has been around from the start. One document per project. Since it has been around so long, there might be some differences in format/missing fields in documents from different years. + +--- + +## [Might be DEPRECATED] `reference` + +Seems to be a mapping between fields we use in genstat or in other places and how we fetch them from LIMS. Not sure if its used. + +--- + + +## `running_notes` + +Keeps all the running notes, one document per note. A partitioned database, which is a bit different, the partition key is the `parent` of the running note, which is commonly the specific project, workset or flowcell. + +--- + +## [WARNING] `sample_requirements` + +Never made it into use, was supposed to keep track of sample requirements for different preps. Still visible on Genomics Status. + +--- + +## `sensorpush` + +Uploades time series data for our freezers and fridges that are connected with a sensorpush sensor. One document per sensor and 24h. Data is uploaded by a script running on ngi_internal polling the sensorpush API. We suspect that the API isn't great and sometimes misses out data, but it could also be sensors that drop out. + +Data is visualized on Genomics Status. + +--- + +## `server_status` + +Tracking storage of server file systems, used to display status on Genomics Status index page. One document per server/system and day. Updated by a TACA command run as a cronjob on ngi-preproc. It's a bit broken since the script is using `df -h` and the network mounted storage systems are not always giving correct stats for that command. + +--- + +## `suggestion_box` + +Keeps track of which items have been added to the suggestion box. Keeps a link to the Jira item and whether its been archived or not. + +--- + +## [DEPRECATED] `taca_flowcells` + +Abandoned project for taca to uploade flowcells I think. Only one document and uploaded 2015. + +--- + +## `userman` + +Database to keep track of the Charon users. + +--- + +## `worksets` + +The worksets database populated by LIMS2DB. One document per workset. + +--- + +## `x_flowcells` + +The Illumina flowcells database, updated by TACA and visualised on Genomics Status. Was named `x` since it was introduced with the HiSeq X machines which had a very different metadata output from the previous generation. + +--- + +## `y_flowcells` + +A database to track the transfer status of all flowcells handled by the transfer script introduced with Project Helix. Updated every hour using a cronjob on ngi-preproc. The name was chosen because it comes after x_flowcells. + +--- + +## `yggdrasil` + +Internal database used by yggdrasil for high level logging. + +--- \ No newline at end of file diff --git a/README.md b/README.md index 477ebff..71038fb 100644 --- a/README.md +++ b/README.md @@ -52,23 +52,24 @@ The easiest way to develop seed data is using the VS Code Dev Container: ## Seed Data Structure -The `seed/` directory contains JSON documents that are loaded into CouchDB on startup. +The `seed/data/` directory contains JSON documents that are loaded into CouchDB on startup. ### Directory Structure ``` seed/ -├── / # Creates a database and loads all JSON files into it -│ ├── doc1.json -│ └── doc2.json -└── *.json # Top-level JSON files are loaded into 'statusdb' database +└── data/ + ├── / # Creates a database and loads all JSON files into it + │ ├── doc1.json + │ └── doc2.json + └── *.json # Top-level JSON files are loaded into 'statusdb' database ``` ### Document Format Each JSON file should contain a single CouchDB document. If the document has an `_id` field, it will be used as the document ID. Otherwise, CouchDB will auto-generate an ID. -Example document (`seed/example_project.json`): +Example document (`seed/data/example_project.json`): ```json { @@ -89,7 +90,7 @@ docker run -p 5984:5984 -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=admin statusdb ## Adding New Seed Data -1. Add JSON files to the `seed/` directory (or subdirectories for specific databases) +1. Add JSON files to the `seed/data/` directory (or subdirectories for specific databases) 2. Commit and push to `main` branch 3. GitHub Actions will automatically build and publish a new image diff --git a/scripts/init-seed-data.sh b/scripts/init-seed-data.sh index f7e04ec..deb5fb3 100644 --- a/scripts/init-seed-data.sh +++ b/scripts/init-seed-data.sh @@ -6,7 +6,7 @@ COUCHDB_HOST="${COUCHDB_HOST:-localhost}" COUCHDB_PORT="${COUCHDB_PORT:-5984}" COUCHDB_USER="${COUCHDB_USER:-admin}" COUCHDB_PASSWORD="${COUCHDB_PASSWORD:-admin}" -SEED_DIR="${SEED_DIR:-/opt/couchdb/seed}" +SEED_DIR="${SEED_DIR:-/opt/couchdb/seed/data}" INIT_MARKER="/opt/couchdb/data/.seed_initialized" COUCHDB_URL="http://${COUCHDB_USER}:${COUCHDB_PASSWORD}@${COUCHDB_HOST}:${COUCHDB_PORT}" diff --git a/seed/agreements/_design_project.json b/seed/data/agreements/_design_project.json similarity index 100% rename from seed/agreements/_design_project.json rename to seed/data/agreements/_design_project.json diff --git a/seed/example_project.json b/seed/data/example_project.json similarity index 100% rename from seed/example_project.json rename to seed/data/example_project.json diff --git a/seed/gs_configs/genstat_defaults.json b/seed/data/gs_configs/genstat_defaults.json similarity index 100% rename from seed/gs_configs/genstat_defaults.json rename to seed/data/gs_configs/genstat_defaults.json diff --git a/seed/gs_configs/gs_teams.json b/seed/data/gs_configs/gs_teams.json similarity index 100% rename from seed/gs_configs/gs_teams.json rename to seed/data/gs_configs/gs_teams.json diff --git a/seed/gs_users/_design_authorized.json b/seed/data/gs_users/_design_authorized.json similarity index 100% rename from seed/gs_users/_design_authorized.json rename to seed/data/gs_users/_design_authorized.json diff --git a/seed/gs_users/test_admin.json b/seed/data/gs_users/test_admin.json similarity index 100% rename from seed/gs_users/test_admin.json rename to seed/data/gs_users/test_admin.json diff --git a/seed/people_assignments/_design_current.json b/seed/data/people_assignments/_design_current.json similarity index 100% rename from seed/people_assignments/_design_current.json rename to seed/data/people_assignments/_design_current.json diff --git a/seed/projects/P12345.json b/seed/data/projects/P12345.json similarity index 100% rename from seed/projects/P12345.json rename to seed/data/projects/P12345.json diff --git a/seed/projects/P12346.json b/seed/data/projects/P12346.json similarity index 100% rename from seed/projects/P12346.json rename to seed/data/projects/P12346.json diff --git a/seed/projects/P12347.json b/seed/data/projects/P12347.json similarity index 100% rename from seed/projects/P12347.json rename to seed/data/projects/P12347.json diff --git a/seed/projects/_design_project.json b/seed/data/projects/_design_project.json similarity index 100% rename from seed/projects/_design_project.json rename to seed/data/projects/_design_project.json diff --git a/seed/running_notes/_design_latest_note_previews.json b/seed/data/running_notes/_design_latest_note_previews.json similarity index 100% rename from seed/running_notes/_design_latest_note_previews.json rename to seed/data/running_notes/_design_latest_note_previews.json diff --git a/seed/sensorpush/_design_entire_document.json b/seed/data/sensorpush/_design_entire_document.json similarity index 100% rename from seed/sensorpush/_design_entire_document.json rename to seed/data/sensorpush/_design_entire_document.json diff --git a/seed/sensorpush/_design_sensor_id.json b/seed/data/sensorpush/_design_sensor_id.json similarity index 100% rename from seed/sensorpush/_design_sensor_id.json rename to seed/data/sensorpush/_design_sensor_id.json diff --git a/seed/server_status/_design_nases.json b/seed/data/server_status/_design_nases.json similarity index 100% rename from seed/server_status/_design_nases.json rename to seed/data/server_status/_design_nases.json diff --git a/seed/server_status/example_status.json b/seed/data/server_status/example_status.json similarity index 100% rename from seed/server_status/example_status.json rename to seed/data/server_status/example_status.json diff --git a/seed/views/agreement_templates/entire_document/by_version.map.js b/seed/views/agreement_templates/entire_document/by_version.map.js new file mode 100644 index 0000000..f214d9d --- /dev/null +++ b/seed/views/agreement_templates/entire_document/by_version.map.js @@ -0,0 +1,3 @@ +function (doc) { + emit(doc["edition"], doc); +} diff --git a/seed/views/agreements/entire_document/project_id.map.js b/seed/views/agreements/entire_document/project_id.map.js new file mode 100644 index 0000000..b075171 --- /dev/null +++ b/seed/views/agreements/entire_document/project_id.map.js @@ -0,0 +1,3 @@ +function (doc) { + emit(doc.project_id, doc); +} diff --git a/seed/views/agreements/project/project_id.map.js b/seed/views/agreements/project/project_id.map.js new file mode 100644 index 0000000..e993bd1 --- /dev/null +++ b/seed/views/agreements/project/project_id.map.js @@ -0,0 +1,3 @@ +function (doc) { + emit(doc.project_id, doc._id); + } \ No newline at end of file diff --git a/seed/views/analysis/RNA_report.map.js b/seed/views/analysis/RNA_report.map.js new file mode 100644 index 0000000..3732ba6 --- /dev/null +++ b/seed/views/analysis/RNA_report.map.js @@ -0,0 +1,19 @@ +function(doc) { + var project_id=Object.keys(doc.samples)[0].split('_')[0]; + var data={}; + for (s in doc.samples){ + data[s]={}; + data[s]['total_reads']=parseInt(doc.samples[s].mapping_statistics.Total_No_reads); + data[s]['unique_reads_mapped']=doc.samples[s].mapping_statistics.bef_dup_rem['%uniq_mapped']; + data[s]['unique_reads_mapped_nodup']=doc.samples[s].mapping_statistics.aft_dup_rem['%uniq_mapped']; + data[s]['CDS_per_kb']=parseFloat(doc.samples[s].read_distribution.CDS_Exons['Tags/Kb']); + data[s]['5UTR_per_kb']=parseFloat(doc.samples[s].read_distribution["5'UTR_Exons"]['Tags/Kb']); + data[s]['3UTR']=parseFloat(doc.samples[s].read_distribution["3'UTR_Exons"]['Tags/Kb']); + data[s]['Introns']=parseFloat(doc.samples[s].read_distribution.Introns['Tags/Kb']); + data[s]['TSS']=parseFloat(doc.samples[s].read_distribution.TSS_up_1kb['Tags/Kb']); + data[s]['TES']=parseFloat(doc.samples[s].read_distribution.TES_down_1kb['Tags/Kb']); + data[s]['%mRNA']=parseFloat(doc.samples[s].read_distribution.mRNA_frac); + data[s]['%rRNA']=parseFloat(doc.samples[s].percent_rRNA); + } + emit(project_id, data); +} diff --git a/seed/views/analysis/multiqc/full_doc.map.js b/seed/views/analysis/multiqc/full_doc.map.js new file mode 100644 index 0000000..dac6ecf --- /dev/null +++ b/seed/views/analysis/multiqc/full_doc.map.js @@ -0,0 +1,5 @@ +function(doc) { + if(doc.entity_type == 'MultiQC_data'){ + emit( doc.project_id, doc); + } +} \ No newline at end of file diff --git a/seed/views/analysis/multiqc/modules.map.js b/seed/views/analysis/multiqc/modules.map.js new file mode 100644 index 0000000..4b828f6 --- /dev/null +++ b/seed/views/analysis/multiqc/modules.map.js @@ -0,0 +1,15 @@ +function(doc) { + if(doc.entity_type == 'MultiQC_data'){ + mqc_modules = []; + for (s in doc.samples){ + mods = Object.keys(doc.samples[s]); + for(i=0; i -1) { + continue; + } + mqc_modules.push(mods[i]); + } + } + emit( doc.project_id, mqc_modules); + } +} \ No newline at end of file diff --git a/seed/views/analysis/names/id_to_name.map.js b/seed/views/analysis/names/id_to_name.map.js new file mode 100644 index 0000000..e144d38 --- /dev/null +++ b/seed/views/analysis/names/id_to_name.map.js @@ -0,0 +1 @@ +function(doc) {emit(doc["_id"], doc["project_name"]);} \ No newline at end of file diff --git a/seed/views/analysis/process_flow/KPI.map.js b/seed/views/analysis/process_flow/KPI.map.js new file mode 100644 index 0000000..52914ef --- /dev/null +++ b/seed/views/analysis/process_flow/KPI.map.js @@ -0,0 +1,59 @@ +function(doc) { + for (sample in doc["samples"]){ + // Get sequencing platform for stratification + var sequencing_platform = doc["details"]["sequencing_platform"] + + // Find arrival date (if present) + var open_date = "0000-00-00" + if (doc["open_date"] > open_date) { + open_date = doc["open_date"] + } + + // Find queue date (if present) + var queued = "0000-00-00" + if (doc["queued"] > queued) { + queued = doc["queued"] + } + + for (library_prep in doc["samples"][sample]["library_prep"]) { + var LP = doc["samples"][sample]["library_prep"][library_prep] + + // Find QC library finish date by looking at the final library validation. + var final_validation = "0000-00-00" + for (lv in LP["library_validation"]) { + var lib_val_fin = LP["library_validation"][lv]["finish_date"] + if (lib_val_fin > final_validation) { + final_validation = lib_val_fin + } + } + + // Find the time a sample is sequenced at by looking at sample runs + // sequencing _start_ date. This is confusing, but it is how Maya + // specified it. + var final_sequence_date = "0000-00-00" + for (sample_run_metrics in LP["sample_run_metrics"]) { + final_sequence_date = LP["sample_run_metrics"][sample_run_metrics]["sequencing_start_date"] + } + + // Collect dates to a KPI object + var KPI = Object() + KPI["Arrival date"] = open_date + KPI["Queue date"] = queued + KPI["QC library finished"] = final_validation + KPI["All samples sequenced"] = final_sequence_date + + emit([sequencing_platform, doc["project_name"], sample, library_prep], KPI) + } + } + + // If no samples have been entered to the project, set all library prep + // and sample sequencing dates to "0000-00-00" + if (!("samples" in doc)) { + var KPI = Object() + KPI["Arrival date"] = open_date + KPI["Queue date"] = queued + KPI["QC library finished"] = "0000-00-00" + KPI["All samples sequenced"] = "0000-00-00" + emit([sequencing_platform, doc["project_name"], null, null], KPI) + } +} diff --git a/seed/views/analysis/process_flow/KPI.reduce.js b/seed/views/analysis/process_flow/KPI.reduce.js new file mode 100644 index 0000000..2c3b7b5 --- /dev/null +++ b/seed/views/analysis/process_flow/KPI.reduce.js @@ -0,0 +1,20 @@ +function(keys, values, rereduce){ + var result = {"Arrival date": "0000-00-00", + "Queue date": "0000-00-00", + "QC library finished": "0000-00-00", + "All samples sequenced": "0000-00-00"} + + for (var i = 0; i < values.length; i++) { + for (k in result) { + if (values[i][k] > result[k]){ + result[k] = values[i][k] + } + else if (values[i][k] == "0000-00-00") { + // We use the date 0000-00-00 to indicate unfinished process + result[k] = "0000-00-00" + } + } + } + + return result +} \ No newline at end of file diff --git a/seed/views/analysis/process_flow/KPI_applications.map.js b/seed/views/analysis/process_flow/KPI_applications.map.js new file mode 100644 index 0000000..e026724 --- /dev/null +++ b/seed/views/analysis/process_flow/KPI_applications.map.js @@ -0,0 +1,59 @@ +function(doc) { + for (sample in doc["samples"]){ + // Get sequencing platform for stratification + var application = doc["application"] + + // Find arrival date (if present) + var open_date = "0000-00-00" + if (doc["open_date"] > open_date) { + open_date = doc["open_date"] + } + + // Find queue date (if present) + var queued = "0000-00-00" + if (doc["queued"] > queued) { + queued = doc["queued"] + } + + for (library_prep in doc["samples"][sample]["library_prep"]) { + var LP = doc["samples"][sample]["library_prep"][library_prep] + + // Find QC library finish date by looking at the final library validation. + var final_validation = "0000-00-00" + for (lv in LP["library_validation"]) { + var lib_val_fin = LP["library_validation"][lv]["finish_date"] + if (lib_val_fin > final_validation) { + final_validation = lib_val_fin + } + } + + // Find the time a sample is sequenced at by looking at sample runs + // sequencing _start_ date. This is confusing, but it is how Maya + // specified it. + var final_sequence_date = "0000-00-00" + for (sample_run_metrics in LP["sample_run_metrics"]) { + final_sequence_date = LP["sample_run_metrics"][sample_run_metrics]["sequencing_start_date"] + } + + // Collect dates to a KPI object + var KPI = Object() + KPI["Arrival date"] = open_date + KPI["Queue date"] = queued + KPI["QC library finished"] = final_validation + KPI["All samples sequenced"] = final_sequence_date + + emit([application, doc["project_name"], sample, library_prep], KPI) + } + } + + // If no samples have been entered to the project, set all library prep + // and sample sequencing dates to "0000-00-00" + if (!("samples" in doc)) { + var KPI = Object() + KPI["Arrival date"] = open_date + KPI["Queue date"] = queued + KPI["QC library finished"] = "0000-00-00" + KPI["All samples sequenced"] = "0000-00-00" + emit([application, doc["project_name"], null, null], KPI) + } +} diff --git a/seed/views/analysis/process_flow/KPI_applications.reduce.js b/seed/views/analysis/process_flow/KPI_applications.reduce.js new file mode 100644 index 0000000..2c3b7b5 --- /dev/null +++ b/seed/views/analysis/process_flow/KPI_applications.reduce.js @@ -0,0 +1,20 @@ +function(keys, values, rereduce){ + var result = {"Arrival date": "0000-00-00", + "Queue date": "0000-00-00", + "QC library finished": "0000-00-00", + "All samples sequenced": "0000-00-00"} + + for (var i = 0; i < values.length; i++) { + for (k in result) { + if (values[i][k] > result[k]){ + result[k] = values[i][k] + } + else if (values[i][k] == "0000-00-00") { + // We use the date 0000-00-00 to indicate unfinished process + result[k] = "0000-00-00" + } + } + } + + return result +} \ No newline at end of file diff --git a/seed/views/analysis/project/name2_id.map.js b/seed/views/analysis/project/name2_id.map.js new file mode 100644 index 0000000..117f53c --- /dev/null +++ b/seed/views/analysis/project/name2_id.map.js @@ -0,0 +1 @@ +function(doc) {emit(doc.project_name, doc._id)} \ No newline at end of file diff --git a/seed/views/analysis/project/name2application.map.js b/seed/views/analysis/project/name2application.map.js new file mode 100644 index 0000000..9f121f8 --- /dev/null +++ b/seed/views/analysis/project/name2application.map.js @@ -0,0 +1 @@ +function(doc) {emit(doc.project_name, doc.application)} \ No newline at end of file diff --git a/seed/views/analysis/project/name2customer_reference.map.js b/seed/views/analysis/project/name2customer_reference.map.js new file mode 100644 index 0000000..bff350e --- /dev/null +++ b/seed/views/analysis/project/name2customer_reference.map.js @@ -0,0 +1 @@ +function(doc) {emit(doc.project_name, doc.customer_reference)} \ No newline at end of file diff --git a/seed/views/analysis/project/name2no_of_samples.map.js b/seed/views/analysis/project/name2no_of_samples.map.js new file mode 100644 index 0000000..69e7350 --- /dev/null +++ b/seed/views/analysis/project/name2no_of_samples.map.js @@ -0,0 +1 @@ +function(doc) {emit(doc.project_name, doc.no_of_samples)} \ No newline at end of file diff --git a/seed/views/analysis/project/name2open_date.map.js b/seed/views/analysis/project/name2open_date.map.js new file mode 100644 index 0000000..ce4299f --- /dev/null +++ b/seed/views/analysis/project/name2open_date.map.js @@ -0,0 +1 @@ +function(doc) {emit(doc.project_name, doc.open_date)} \ No newline at end of file diff --git a/seed/views/analysis/project/name2project_id.map.js b/seed/views/analysis/project/name2project_id.map.js new file mode 100644 index 0000000..d459611 --- /dev/null +++ b/seed/views/analysis/project/name2project_id.map.js @@ -0,0 +1 @@ +function(doc) {emit(doc.project_name, doc.project_id)} \ No newline at end of file diff --git a/seed/views/analysis/project/name2reference_genome.map.js b/seed/views/analysis/project/name2reference_genome.map.js new file mode 100644 index 0000000..f5030a9 --- /dev/null +++ b/seed/views/analysis/project/name2reference_genome.map.js @@ -0,0 +1 @@ +function(doc) {emit(doc.project_name, doc.reference_genome)} \ No newline at end of file diff --git a/seed/views/analysis/project/name2uppnex_id.map.js b/seed/views/analysis/project/name2uppnex_id.map.js new file mode 100644 index 0000000..eebb87d --- /dev/null +++ b/seed/views/analysis/project/name2uppnex_id.map.js @@ -0,0 +1 @@ +function(doc) {emit(doc.project_name, doc.uppnex_id)} \ No newline at end of file diff --git a/seed/views/analysis/project/project_id.map.js b/seed/views/analysis/project/project_id.map.js new file mode 100644 index 0000000..a99573f --- /dev/null +++ b/seed/views/analysis/project/project_id.map.js @@ -0,0 +1,4 @@ +function(doc) { + var project_id=Object.keys(doc.samples)[0].split('_')[0]; + emit(project_id, doc); +} \ No newline at end of file diff --git a/seed/views/analysis/project/project_name.map.js b/seed/views/analysis/project/project_name.map.js new file mode 100644 index 0000000..117f53c --- /dev/null +++ b/seed/views/analysis/project/project_name.map.js @@ -0,0 +1 @@ +function(doc) {emit(doc.project_name, doc._id)} \ No newline at end of file diff --git a/seed/views/analysis/reports/RNA_report.map.js b/seed/views/analysis/reports/RNA_report.map.js new file mode 100644 index 0000000..47e3f7c --- /dev/null +++ b/seed/views/analysis/reports/RNA_report.map.js @@ -0,0 +1,19 @@ +function(doc) { + var project_id=Object.keys(doc.samples)[0].split('_')[0]; + var data={}; + for (s in doc.samples){ + data[s]={}; + data[s]['total_reads']=parseInt(doc.samples[s].mapping_statistics.Total_No_reads); + data[s]['unique_reads_mapped']=doc.samples[s].mapping_statistics.bef_dup_rem['%uniq_mapped']; + data[s]['unique_reads_mapped_nodup']=doc.samples[s].mapping_statistics.aft_dup_rem['%uniq_mapped']; + data[s]['CDS_per_kb']=parseFloat(doc.samples[s].read_distribution.CDS_Exons['Tags/Kb']); + data[s]['5UTR_per_kb']=parseFloat(doc.samples[s].read_distribution["5'UTR_Exons"]['Tags/Kb']); + data[s]['3UTR']=parseFloat(doc.samples[s].read_distribution["3'UTR_Exons"]['Tags/Kb']); + data[s]['Introns']=parseFloat(doc.samples[s].read_distribution.Introns['Tags/Kb']); + data[s]['TSS']=parseFloat(doc.samples[s].read_distribution.TSS_up_1kb['Tags/Kb']); + data[s]['TES']=parseFloat(doc.samples[s].read_distribution.TES_down_1kb['Tags/Kb']); + data[s]['%mRNA']=parseFloat(doc.samples[s].read_distribution.mRNA_frac); + data[s]['%rRNA']=parseFloat(doc.samples[s].percent_rRNA); + } + emit(project_id, data); +} \ No newline at end of file diff --git a/seed/views/analysis/samples/samp_top3.map.js b/seed/views/analysis/samples/samp_top3.map.js new file mode 100644 index 0000000..a09b61e --- /dev/null +++ b/seed/views/analysis/samples/samp_top3.map.js @@ -0,0 +1,16 @@ +function(doc) { + samples={} + for (sample in doc["samples"]) { + s = doc["samples"][sample]; + gene_dict={}; + for (gene in s["top_dups"]["top3_genes_based_on_normed_counts_duprem"]) { + g=s["top_dups"]["top3_genes_based_on_normed_counts_duprem"][gene] + gene_dict[gene]=[g['counts_noremed_by_gene_lengt']['no_dupl/(total_no_counts)'],g['counts_not_noremed']['no_dupl/(total_no_counts)']] + } + emit([sample,{"counts":s["top_dups"]['total_counts_maped_to_annotated_genes'],"counts_duprem":s["top_dups"]['total_counts_maped_to_annotated_genes_(duplicates_removed)'],'no_feat':s["top_dups"]['no_feature_withdup'],'no_feat_duprem':s["top_dups"]['no_feature_duprem']}],gene_dict) + +} +} + + + \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/full_doc/pj_run_lane_sample_to_doc.map.js b/seed/views/bioinfo_analysis/full_doc/pj_run_lane_sample_to_doc.map.js new file mode 100644 index 0000000..1216c74 --- /dev/null +++ b/seed/views/bioinfo_analysis/full_doc/pj_run_lane_sample_to_doc.map.js @@ -0,0 +1,3 @@ +function(doc) { + emit([doc.project_id, doc.run_id, doc.lane, doc.sample], doc); +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/full_doc/pj_run_to_doc.map.js b/seed/views/bioinfo_analysis/full_doc/pj_run_to_doc.map.js new file mode 100644 index 0000000..3406ad8 --- /dev/null +++ b/seed/views/bioinfo_analysis/full_doc/pj_run_to_doc.map.js @@ -0,0 +1,3 @@ +function(doc) { + emit([doc.project_id, doc.run_id], doc); +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/full_doc/pj_sample_run_lane_to_doc.map.js b/seed/views/bioinfo_analysis/full_doc/pj_sample_run_lane_to_doc.map.js new file mode 100644 index 0000000..1445472 --- /dev/null +++ b/seed/views/bioinfo_analysis/full_doc/pj_sample_run_lane_to_doc.map.js @@ -0,0 +1,4 @@ +function(doc) { +if ('sample' in doc && 'lane' in doc) { + emit([doc.project_id, doc.sample, doc.run_id, doc.lane], doc); +}} diff --git a/seed/views/bioinfo_analysis/full_doc/proj_run_lane_to_doc.js b/seed/views/bioinfo_analysis/full_doc/proj_run_lane_to_doc.js new file mode 100644 index 0000000..260c4c4 --- /dev/null +++ b/seed/views/bioinfo_analysis/full_doc/proj_run_lane_to_doc.js @@ -0,0 +1,3 @@ +function(doc) { + emit([doc.project_id, doc.run_id, doc.lane], doc); +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/full_doc/proj_run_lane_to_doc.map.js b/seed/views/bioinfo_analysis/full_doc/proj_run_lane_to_doc.map.js new file mode 100644 index 0000000..260c4c4 --- /dev/null +++ b/seed/views/bioinfo_analysis/full_doc/proj_run_lane_to_doc.map.js @@ -0,0 +1,3 @@ +function(doc) { + emit([doc.project_id, doc.run_id, doc.lane], doc); +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/full_doc/project_to_doc.js b/seed/views/bioinfo_analysis/full_doc/project_to_doc.js new file mode 100644 index 0000000..4901df5 --- /dev/null +++ b/seed/views/bioinfo_analysis/full_doc/project_to_doc.js @@ -0,0 +1,5 @@ +function(doc) { + if (doc.sample != null && doc.lane != null && doc.run_id != null) { + emit(doc.project_id, doc); + } +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/full_doc/project_to_doc.map.js b/seed/views/bioinfo_analysis/full_doc/project_to_doc.map.js new file mode 100644 index 0000000..4901df5 --- /dev/null +++ b/seed/views/bioinfo_analysis/full_doc/project_to_doc.map.js @@ -0,0 +1,5 @@ +function(doc) { + if (doc.sample != null && doc.lane != null && doc.run_id != null) { + emit(doc.project_id, doc); + } +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/full_doc/run_id_to_doc.js b/seed/views/bioinfo_analysis/full_doc/run_id_to_doc.js new file mode 100644 index 0000000..60561a0 --- /dev/null +++ b/seed/views/bioinfo_analysis/full_doc/run_id_to_doc.js @@ -0,0 +1,3 @@ +function(doc) { + emit([doc.run_id], doc); +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/full_doc/run_id_to_doc.map.js b/seed/views/bioinfo_analysis/full_doc/run_id_to_doc.map.js new file mode 100644 index 0000000..60561a0 --- /dev/null +++ b/seed/views/bioinfo_analysis/full_doc/run_id_to_doc.map.js @@ -0,0 +1,3 @@ +function(doc) { + emit([doc.run_id], doc); +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/general/incoming_projectids.map.js b/seed/views/bioinfo_analysis/general/incoming_projectids.map.js new file mode 100644 index 0000000..599a8d2 --- /dev/null +++ b/seed/views/bioinfo_analysis/general/incoming_projectids.map.js @@ -0,0 +1,5 @@ +function(doc) { + if (doc.status == "Incoming"){ + emit(doc.project_id, null); +} +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/general/incoming_projectids.reduce.js b/seed/views/bioinfo_analysis/general/incoming_projectids.reduce.js new file mode 100644 index 0000000..42e5a14 --- /dev/null +++ b/seed/views/bioinfo_analysis/general/incoming_projectids.reduce.js @@ -0,0 +1,3 @@ +function(key,values){ +return true; +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/general/not_ongoing_projectids.map.js b/seed/views/bioinfo_analysis/general/not_ongoing_projectids.map.js new file mode 100644 index 0000000..91e641a --- /dev/null +++ b/seed/views/bioinfo_analysis/general/not_ongoing_projectids.map.js @@ -0,0 +1,5 @@ +function(doc) { +if (doc.status != "Ongoing"){ + emit(doc.run_id, doc); +} +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/general/not_ongoing_runids.map.js b/seed/views/bioinfo_analysis/general/not_ongoing_runids.map.js new file mode 100644 index 0000000..91e641a --- /dev/null +++ b/seed/views/bioinfo_analysis/general/not_ongoing_runids.map.js @@ -0,0 +1,5 @@ +function(doc) { +if (doc.status != "Ongoing"){ + emit(doc.run_id, doc); +} +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/general/ongoing_projectids.map.js b/seed/views/bioinfo_analysis/general/ongoing_projectids.map.js new file mode 100644 index 0000000..336d98e --- /dev/null +++ b/seed/views/bioinfo_analysis/general/ongoing_projectids.map.js @@ -0,0 +1,5 @@ +function(doc) { + if (doc.status == "Ongoing"){ + emit(doc.project_id, null); +} +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/general/ongoing_projectids.reduce.js b/seed/views/bioinfo_analysis/general/ongoing_projectids.reduce.js new file mode 100644 index 0000000..42e5a14 --- /dev/null +++ b/seed/views/bioinfo_analysis/general/ongoing_projectids.reduce.js @@ -0,0 +1,3 @@ +function(key,values){ +return true; +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/genomics_dashboard/run_lane_sample_status.js b/seed/views/bioinfo_analysis/genomics_dashboard/run_lane_sample_status.js new file mode 100644 index 0000000..8fdbd55 --- /dev/null +++ b/seed/views/bioinfo_analysis/genomics_dashboard/run_lane_sample_status.js @@ -0,0 +1,12 @@ +function(doc) { + if (doc.sample != null && doc.lane != null && doc.run_id != null) { + last_entry = "0000-00-00"; + for (entry in doc.values) { + if (entry > last_entry) { + last_entry = entry; + } + } + run_lane = doc.run_id + "_" + doc.lane; + emit([doc.project_id, run_lane], doc['values'][last_entry]); + } +} diff --git a/seed/views/bioinfo_analysis/genomics_dashboard/run_lane_sample_status.map.js b/seed/views/bioinfo_analysis/genomics_dashboard/run_lane_sample_status.map.js new file mode 100644 index 0000000..53c06f9 --- /dev/null +++ b/seed/views/bioinfo_analysis/genomics_dashboard/run_lane_sample_status.map.js @@ -0,0 +1,12 @@ +function(doc) { + if (doc.sample != null && doc.lane != null && doc.run_id != null) { + last_entry = "0000-00-00"; + for (entry in doc.values) { + if (entry > last_entry) { + last_entry = entry; + } + } + run_lane = doc.run_id + "_" + doc.lane; + emit([doc.project_id, run_lane], doc['values'][last_entry]); + } +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/keys/pj_run.map.js b/seed/views/bioinfo_analysis/keys/pj_run.map.js new file mode 100644 index 0000000..30a6fb3 --- /dev/null +++ b/seed/views/bioinfo_analysis/keys/pj_run.map.js @@ -0,0 +1,3 @@ +function(doc) { + emit([doc.project_id, doc.run_id], doc._id); +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/keys/run_id.map.js b/seed/views/bioinfo_analysis/keys/run_id.map.js new file mode 100644 index 0000000..793a389 --- /dev/null +++ b/seed/views/bioinfo_analysis/keys/run_id.map.js @@ -0,0 +1,3 @@ +function(doc) { + emit( doc.run_id, doc._id); +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/latest_data/project_id.map.js b/seed/views/bioinfo_analysis/latest_data/project_id.map.js new file mode 100644 index 0000000..e933bc0 --- /dev/null +++ b/seed/views/bioinfo_analysis/latest_data/project_id.map.js @@ -0,0 +1,22 @@ +function(doc) { + summary={}; + summary[doc.run_id]={}; + default_date=new Date(1989,03,11) //Happy birthday + for (datestring in doc.values){ + new_date=new Date(datestring); + if (new_date>default_date){ + default_date=new_date; + for (key in doc.values[datestring]){ + summary[doc.run_id][key]=doc.values[datestring][key]; + } + //summary[doc.run_id]=doc.values[datestring]; + summary[doc.run_id].timestamp=default_date.toISOString(); + + } + } + summary[doc.run_id]["project_id"]=doc.project_id; + summary[doc.run_id]["status"]=doc.status; + + + emit(doc.project_id, summary); +} \ No newline at end of file diff --git a/seed/views/bioinfo_analysis/latest_data/sample_id.map.js b/seed/views/bioinfo_analysis/latest_data/sample_id.map.js new file mode 100644 index 0000000..ce9ae5e --- /dev/null +++ b/seed/views/bioinfo_analysis/latest_data/sample_id.map.js @@ -0,0 +1,21 @@ +function(doc) { + summary={}; + default_date=new Date(1989,03,11) //Happy birthday + for (datestring in doc.values){ + new_date=new Date(datestring); + if (new_date>default_date){ + default_date=new_date; + for (key in doc.values[datestring]){ + summary[key]=doc.values[datestring][key]; + } + //summary=doc.values[datestring]; + summary.timestamp=default_date.toISOString(); + + } + } + + if (doc.sample != null){ + emit([doc.project_id, doc.run_id, doc.lane, doc.sample], summary); + } +} + diff --git a/seed/views/bioinfo_analysis/latest_data/sample_id_open.map.js b/seed/views/bioinfo_analysis/latest_data/sample_id_open.map.js new file mode 100644 index 0000000..6b6f9c0 --- /dev/null +++ b/seed/views/bioinfo_analysis/latest_data/sample_id_open.map.js @@ -0,0 +1,28 @@ +function(doc) { + summary={}; + default_date=new Date(1989,03,11) //Happy birthday + for (datestring in doc.values){ + new_date=new Date(datestring); + if (new_date>default_date){ + default_date=new_date; + for (key in doc.values[datestring]){ + summary[key]=doc.values[datestring][key]; + } + //summary=doc.values[datestring]; + summary.timestamp=default_date.toISOString(); + } + } + if('instrument_type' in doc){ + summary.instrument_type = doc.instrument_type; + } + else{ + summary.instrument_type = 'illumina'; + } + if('instrument' in doc){ + summary.instrument = doc.instrument; + } + // needed for the delivery page, to show only projects which were not closed + if (doc.sample != null && (summary['sample_status'] != 'Closed' && !doc.hasOwnProperty('project_closed'))) { + emit([doc.project_id, doc.run_id, doc.lane, doc.sample], summary); + } +} diff --git a/seed/views/bioinfo_analysis/status/pj_run.map.js b/seed/views/bioinfo_analysis/status/pj_run.map.js new file mode 100644 index 0000000..fb01b01 --- /dev/null +++ b/seed/views/bioinfo_analysis/status/pj_run.map.js @@ -0,0 +1,3 @@ +function(doc) { + emit([doc.project_id, doc.run_id], doc.status); +} \ No newline at end of file diff --git a/seed/views/biomek_logs/dates/timestamp.map.js b/seed/views/biomek_logs/dates/timestamp.map.js new file mode 100644 index 0000000..7150bc7 --- /dev/null +++ b/seed/views/biomek_logs/dates/timestamp.map.js @@ -0,0 +1,4 @@ +function(doc) { + start_date = new Date(doc.start_time); + emit(start_date, doc); + } \ No newline at end of file diff --git a/seed/views/biomek_logs/names/run_finished.map.js b/seed/views/biomek_logs/names/run_finished.map.js new file mode 100644 index 0000000..460003f --- /dev/null +++ b/seed/views/biomek_logs/names/run_finished.map.js @@ -0,0 +1,3 @@ +function (doc) { + emit([doc.file_name, doc.inst_id], doc.run_finished); + } \ No newline at end of file diff --git a/seed/views/charon/filters/deletedfilter.filter.js b/seed/views/charon/filters/deletedfilter.filter.js new file mode 100644 index 0000000..7cd0473 --- /dev/null +++ b/seed/views/charon/filters/deletedfilter.filter.js @@ -0,0 +1 @@ +function(doc, req) { return !doc._deleted; }; \ No newline at end of file diff --git a/seed/views/charon/filters/nologfilter.filter.js b/seed/views/charon/filters/nologfilter.filter.js new file mode 100644 index 0000000..e4c2a00 --- /dev/null +++ b/seed/views/charon/filters/nologfilter.filter.js @@ -0,0 +1 @@ +function(doc, req) { return doc.charon_doctype !== 'log' }; \ No newline at end of file diff --git a/seed/views/charon/internal/sampleids_to_projectids.map.js b/seed/views/charon/internal/sampleids_to_projectids.map.js new file mode 100644 index 0000000..d55607f --- /dev/null +++ b/seed/views/charon/internal/sampleids_to_projectids.map.js @@ -0,0 +1,8 @@ + +function(doc) { + if (doc.charon_doctype != 'sample'){ + return; +}else{ + emit(doc.sampleid, doc.projectid); +} +} \ No newline at end of file diff --git a/seed/views/charon/libprep/count.map.js b/seed/views/charon/libprep/count.map.js new file mode 100644 index 0000000..9958118 --- /dev/null +++ b/seed/views/charon/libprep/count.map.js @@ -0,0 +1,8 @@ +/* Charon + Index libprep documents by [projectid, sampleid]. + Value: 1. +*/ +function(doc) { + if (doc.charon_doctype !== 'libprep') return; + emit([doc.projectid, doc.sampleid], 1); +} diff --git a/seed/views/charon/libprep/count.reduce.js b/seed/views/charon/libprep/count.reduce.js new file mode 100644 index 0000000..768b109 --- /dev/null +++ b/seed/views/charon/libprep/count.reduce.js @@ -0,0 +1 @@ +_count \ No newline at end of file diff --git a/seed/views/charon/libprep/libprepid.map.js b/seed/views/charon/libprep/libprepid.map.js new file mode 100644 index 0000000..29293fc --- /dev/null +++ b/seed/views/charon/libprep/libprepid.map.js @@ -0,0 +1,8 @@ +/* Charon + Index libprep documents by [projectid, sampleid, libprepid]. + Value: null. +*/ +function(doc) { + if (doc.charon_doctype !== 'libprep') return; + emit([doc.projectid, doc.sampleid, doc.libprepid], null); +} diff --git a/seed/views/charon/libprep/modified.map.js b/seed/views/charon/libprep/modified.map.js new file mode 100644 index 0000000..822fade --- /dev/null +++ b/seed/views/charon/libprep/modified.map.js @@ -0,0 +1,11 @@ +/* Charon + Index libprep documents by modified. + Value: [projectid, sampleid, libprepid]. +*/ + + +function(doc) { + if (doc.charon_doctype !== 'libprep') return; + if (!doc.modified) return; + emit(doc.modified, [doc.projectid, doc.sampleid, doc.libprepid]); +} diff --git a/seed/views/charon/log/doc.map.js b/seed/views/charon/log/doc.map.js new file mode 100644 index 0000000..a70e1be --- /dev/null +++ b/seed/views/charon/log/doc.map.js @@ -0,0 +1,9 @@ +/* Charon + Index log documents by doc. + Value: timestamp. +*/ + +function(doc) { + if (doc.charon_doctype !== 'log') return; + emit(doc.doc, doc.timestamp); +} diff --git a/seed/views/charon/project/modified.map.js b/seed/views/charon/project/modified.map.js new file mode 100644 index 0000000..72b2a98 --- /dev/null +++ b/seed/views/charon/project/modified.map.js @@ -0,0 +1,10 @@ +/* Charon + Index project documents by modified. + Value: projectid. +*/ + +function(doc) { + if (doc.charon_doctype !== 'project') return; + if (!doc.modified) return; + emit(doc.modified, doc.projectid); +} diff --git a/seed/views/charon/project/name.map.js b/seed/views/charon/project/name.map.js new file mode 100644 index 0000000..d07d083 --- /dev/null +++ b/seed/views/charon/project/name.map.js @@ -0,0 +1,9 @@ +/* Charon + Index project documents by name. + Value: projectid. +*/ +function(doc) { + if (doc.charon_doctype !== 'project') return; + if (!doc.name) return; + emit(doc.name, doc.projectid); +} diff --git a/seed/views/charon/project/not_done.map.js b/seed/views/charon/project/not_done.map.js new file mode 100644 index 0000000..6796c5b --- /dev/null +++ b/seed/views/charon/project/not_done.map.js @@ -0,0 +1,6 @@ +/*emits only not done projects*/ +function(doc) { + if (doc.charon_doctype === 'project' && doc.status !== 'CLOSED'){ + emit(doc.projectid, doc); + } +} diff --git a/seed/views/charon/project/projectid.map.js b/seed/views/charon/project/projectid.map.js new file mode 100644 index 0000000..645e665 --- /dev/null +++ b/seed/views/charon/project/projectid.map.js @@ -0,0 +1,8 @@ +/* Charon + Index project documents by projectid. + Value: projectname, or null. +*/ +function(doc) { + if (doc.charon_doctype !== 'project') return; + emit(doc.projectid, doc.projectname || null); +} diff --git a/seed/views/charon/project/splitname.map.js b/seed/views/charon/project/splitname.map.js new file mode 100644 index 0000000..efb8325 --- /dev/null +++ b/seed/views/charon/project/splitname.map.js @@ -0,0 +1,12 @@ +/* Charon + Index project documents by name split at first dot '.'. + Value: projectid. +*/ +function(doc) { + if (doc.charon_doctype !== 'project') return; + if (!doc.name) return; + emit(doc.name, doc.projectid); + var parts = doc.name.split(".", 2); + if (parts.length < 2) return; + emit(parts[1], doc.projectid); +} diff --git a/seed/views/charon/sample/analyzed_failed.map.js b/seed/views/charon/sample/analyzed_failed.map.js new file mode 100644 index 0000000..ae9b406 --- /dev/null +++ b/seed/views/charon/sample/analyzed_failed.map.js @@ -0,0 +1,7 @@ +/*Returns all samples taht have a 'FAILED' status*/ + +function(doc) { + if (doc.charon_doctype === 'sample' && (doc.analysis_status == 'FAILED' || doc.analysis_status == 'ANALYZED')){ + emit([doc.projectid, doc.sampleid], doc); + } +} diff --git a/seed/views/charon/sample/count.map.js b/seed/views/charon/sample/count.map.js new file mode 100644 index 0000000..03f0ba7 --- /dev/null +++ b/seed/views/charon/sample/count.map.js @@ -0,0 +1,8 @@ +/* Charon + Index sample documents by projectid. + Value: 1. +*/ +function(doc) { + if (doc.charon_doctype !== 'sample') return; + emit(doc.projectid, 1); +} diff --git a/seed/views/charon/sample/count.reduce.js b/seed/views/charon/sample/count.reduce.js new file mode 100644 index 0000000..768b109 --- /dev/null +++ b/seed/views/charon/sample/count.reduce.js @@ -0,0 +1 @@ +_count \ No newline at end of file diff --git a/seed/views/charon/sample/count_delivered.map.js b/seed/views/charon/sample/count_delivered.map.js new file mode 100644 index 0000000..eb9c0b0 --- /dev/null +++ b/seed/views/charon/sample/count_delivered.map.js @@ -0,0 +1,7 @@ +/* Charon + Index sample documents by projectid. + Value: 1. +*/ +function(doc) { + if (doc.charon_doctype === 'sample' && doc.delivery_status === "DELIVERED") emit(doc.projectid, 1); +} diff --git a/seed/views/charon/sample/count_delivered.reduce.js b/seed/views/charon/sample/count_delivered.reduce.js new file mode 100644 index 0000000..768b109 --- /dev/null +++ b/seed/views/charon/sample/count_delivered.reduce.js @@ -0,0 +1 @@ +_count \ No newline at end of file diff --git a/seed/views/charon/sample/count_done.map.js b/seed/views/charon/sample/count_done.map.js new file mode 100644 index 0000000..29cdfb5 --- /dev/null +++ b/seed/views/charon/sample/count_done.map.js @@ -0,0 +1,7 @@ +/* Charon + Index sample documents by projectid. + Value: 1. +*/ +function(doc) { + if (doc.charon_doctype === 'sample' && doc.analysis_status === "ANALYZED") emit(doc.projectid, 1); +} diff --git a/seed/views/charon/sample/count_done.reduce.js b/seed/views/charon/sample/count_done.reduce.js new file mode 100644 index 0000000..768b109 --- /dev/null +++ b/seed/views/charon/sample/count_done.reduce.js @@ -0,0 +1 @@ +_count \ No newline at end of file diff --git a/seed/views/charon/sample/done.map.js b/seed/views/charon/sample/done.map.js new file mode 100644 index 0000000..beb1899 --- /dev/null +++ b/seed/views/charon/sample/done.map.js @@ -0,0 +1,7 @@ +/*Returns all samples taht have a 'not done' status*/ + +function(doc) { + if (doc.charon_doctype === 'sample' && doc.analysis_status == 'ANALYZED'){ + emit([doc.projectid, doc.sampleid], doc); + } +} diff --git a/seed/views/charon/sample/failed.map.js b/seed/views/charon/sample/failed.map.js new file mode 100644 index 0000000..0847eee --- /dev/null +++ b/seed/views/charon/sample/failed.map.js @@ -0,0 +1,7 @@ +/*Returns all samples taht have a 'FAILED' status*/ + +function(doc) { + if (doc.charon_doctype === 'sample' && doc.analysis_status == 'FAILED'){ + emit([doc.projectid, doc.sampleid], doc); + } +} diff --git a/seed/views/charon/sample/modified.map.js b/seed/views/charon/sample/modified.map.js new file mode 100644 index 0000000..1eec17f --- /dev/null +++ b/seed/views/charon/sample/modified.map.js @@ -0,0 +1,9 @@ +/* Charon + Index sample documents by modified. + Value: [projectid, sampleid]. +*/ +function(doc) { + if (doc.charon_doctype !== 'sample') return; + if (!doc.modified) return; + emit(doc.modified, [doc.projectid, doc.sampleid]); +} diff --git a/seed/views/charon/sample/not_done.map.js b/seed/views/charon/sample/not_done.map.js new file mode 100644 index 0000000..7c407ab --- /dev/null +++ b/seed/views/charon/sample/not_done.map.js @@ -0,0 +1,6 @@ +/*Returns all samples taht have a 'not done' status*/ +function(doc) { + if (doc.charon_doctype === 'sample' && doc.analysis_status !== 'ANALYZED'){ + emit([doc.projectid, doc.sampleid], doc); + } +} diff --git a/seed/views/charon/sample/running.map.js b/seed/views/charon/sample/running.map.js new file mode 100644 index 0000000..e351561 --- /dev/null +++ b/seed/views/charon/sample/running.map.js @@ -0,0 +1,7 @@ +/*Returns all samples taht have a 'UNDER_ANALYSIS' status*/ + +function(doc) { + if (doc.charon_doctype === 'sample' && doc.analysis_status == 'UNDER_ANALYSIS'){ + emit([doc.projectid, doc.sampleid], doc); + } +} diff --git a/seed/views/charon/sample/sampleid.map.js b/seed/views/charon/sample/sampleid.map.js new file mode 100644 index 0000000..91a6aa9 --- /dev/null +++ b/seed/views/charon/sample/sampleid.map.js @@ -0,0 +1,8 @@ +/* Charon + Index sample documents by [projectid, sampleid]. + Value: null. +*/ +function(doc) { + if (doc.charon_doctype !== 'sample') return; + emit([doc.projectid, doc.sampleid], null); +} diff --git a/seed/views/charon/sample/sequenced.map.js b/seed/views/charon/sample/sequenced.map.js new file mode 100644 index 0000000..3067020 --- /dev/null +++ b/seed/views/charon/sample/sequenced.map.js @@ -0,0 +1,5 @@ +function(doc) { + if (doc.charon_doctype === 'seqrun'){ + emit([doc.projectid, doc.sampleid], 1); + } +} \ No newline at end of file diff --git a/seed/views/charon/sample/sequenced.reduce.js b/seed/views/charon/sample/sequenced.reduce.js new file mode 100644 index 0000000..3eed19a --- /dev/null +++ b/seed/views/charon/sample/sequenced.reduce.js @@ -0,0 +1,3 @@ +function(map, value, rereduce){ + return 1; +} \ No newline at end of file diff --git a/seed/views/charon/sample/summary_count.map.js b/seed/views/charon/sample/summary_count.map.js new file mode 100644 index 0000000..8442a26 --- /dev/null +++ b/seed/views/charon/sample/summary_count.map.js @@ -0,0 +1,39 @@ +/* Charon + counts samples by type. + Value: 1. +*/ +function(doc) { + seq_sa=[]; + if (doc.charon_doctype === 'sample'){ + emit('TOTAL', 1); + if (doc.status === 'ABORTED'){ + emit('ABORTED', 1); + emit(doc.projectid+'_ABORTED', 1); + } + emit(doc.projectid+'_TOTAL', 1); + emit('TOTAL_COV', doc.total_autosomal_coverage); + emit(doc.projectid+'_TOTAL_COV', doc.total_autosomal_coverage); + if (doc.analysis_status === 'ANALYZED'){ + emit('ANALYZED', 1); + emit(doc.projectid+'_ANALYZED', 1); + if (doc.status !== 'ABORTED'){ + emit('ANALYZED_UNAB', 1); + emit(doc.projectid+'_ANALYZED_UNAB', 1); + } + } + else if (doc.analysis_status === 'UNDER_ANALYSIS'){ + emit('UNDER_ANALYSIS', 1); + emit(doc.projectid+'_UNDER_ANALYSIS', 1); + } + else if (doc.analysis_status === 'FAILED'){ + emit('FAILED', 1); + emit(doc.projectid+'_FAILED', 1); + } + }else if (doc.charon_doctype === 'seqrun'){ + if (seq_sa.indexOf(doc.sampleid) == -1){ + seq_sa.push(doc.sampleid); + emit('SEQUENCED', 1); + emit(doc.projectid+'_SEQUENCED', 1); + } + } +} \ No newline at end of file diff --git a/seed/views/charon/sample/summary_count.reduce.js b/seed/views/charon/sample/summary_count.reduce.js new file mode 100644 index 0000000..79f412b --- /dev/null +++ b/seed/views/charon/sample/summary_count.reduce.js @@ -0,0 +1 @@ +_sum \ No newline at end of file diff --git a/seed/views/charon/sample/total_coverage.map.js b/seed/views/charon/sample/total_coverage.map.js new file mode 100644 index 0000000..5d2e6a5 --- /dev/null +++ b/seed/views/charon/sample/total_coverage.map.js @@ -0,0 +1,7 @@ + +function(doc) { + if (doc.charon_doctype === 'sample'){ + emit('TOTAL', doc.total_autosomal_coverage); + } +} + diff --git a/seed/views/charon/sample/total_coverage.reduce.js b/seed/views/charon/sample/total_coverage.reduce.js new file mode 100644 index 0000000..79f412b --- /dev/null +++ b/seed/views/charon/sample/total_coverage.reduce.js @@ -0,0 +1 @@ +_sum \ No newline at end of file diff --git a/seed/views/charon/seqrun/count.map.js b/seed/views/charon/seqrun/count.map.js new file mode 100644 index 0000000..32da0ae --- /dev/null +++ b/seed/views/charon/seqrun/count.map.js @@ -0,0 +1,9 @@ +/* Charon + Index seqrun documents by [projectid, sampleid, libprepid]. + Value: 1. +*/ + +function(doc) { + if (doc.charon_doctype !== 'seqrun') return; + emit([doc.projectid, doc.sampleid, doc.libprepid], 1); +} diff --git a/seed/views/charon/seqrun/count.reduce.js b/seed/views/charon/seqrun/count.reduce.js new file mode 100644 index 0000000..768b109 --- /dev/null +++ b/seed/views/charon/seqrun/count.reduce.js @@ -0,0 +1 @@ +_count \ No newline at end of file diff --git a/seed/views/charon/seqrun/seqrunid.map.js b/seed/views/charon/seqrun/seqrunid.map.js new file mode 100644 index 0000000..3bec431 --- /dev/null +++ b/seed/views/charon/seqrun/seqrunid.map.js @@ -0,0 +1,8 @@ +/* Charon + Index seqrun documents by [projectid, sampleid, libprepid, seqrunid]. + Value: null. +*/ +function(doc) { + if (doc.charon_doctype !== 'seqrun') return; + emit([doc.projectid, doc.sampleid, doc.libprepid, doc.seqrunid], null); +} diff --git a/seed/views/charon/test/test.map.js b/seed/views/charon/test/test.map.js new file mode 100644 index 0000000..5b2acc9 --- /dev/null +++ b/seed/views/charon/test/test.map.js @@ -0,0 +1,10 @@ +/* Charon + Index libprep documents by modified. + Value: [projectid, sampleid, libprepid]. +*/ + +function(doc) { + if (doc.charon_doctype !== 'libprep') return; + if (!doc.modified) return; + emit(doc.modified, [doc.projectid, doc.sampleid, doc.libprepid]); +} diff --git a/seed/views/charon/user/api_token.map.js b/seed/views/charon/user/api_token.map.js new file mode 100644 index 0000000..6225d9f --- /dev/null +++ b/seed/views/charon/user/api_token.map.js @@ -0,0 +1,8 @@ +/* Charon + Index user documents by API token. + Value: email. +*/ +function(doc) { + if (doc.charon_doctype !== 'user') return; + emit(doc.api_token, doc.email); +} diff --git a/seed/views/charon/user/email.map.js b/seed/views/charon/user/email.map.js new file mode 100644 index 0000000..0f73562 --- /dev/null +++ b/seed/views/charon/user/email.map.js @@ -0,0 +1,9 @@ +/* Charon + Index user documents by email. + Value: null. +*/ + +function(doc) { + if (doc.charon_doctype !== 'user') return; + emit(doc.email, null); +} diff --git a/seed/views/charon/user/name.map.js b/seed/views/charon/user/name.map.js new file mode 100644 index 0000000..8512d34 --- /dev/null +++ b/seed/views/charon/user/name.map.js @@ -0,0 +1,15 @@ +/* Charon + Index user documents by name and parts of the name. + Value: email. +*/ +function(doc) { + if (doc.charon_doctype !== 'user') return; + if (!doc.name) return; + emit(doc.name, doc.email); + var parts = doc.name.split(" "); + if (parts.length > 1) { + for (var i=0; i0){ + summary['demultiplexing']='Done'; + } + /*yield is in Mb, but is displayed in Gb*/ + summary['yield']=0; + var undetermined={1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0}; + + for(barcode in doc.illumina['Demultiplex_Stats']['Barcode_lane_statistics']){ + if (doc.illumina['Demultiplex_Stats']['Barcode_lane_statistics'][barcode]['Index'] == 'Undetermined'){ + undetermined[doc.illumina['Demultiplex_Stats']['Barcode_lane_statistics'][barcode]['Lane']]+=1; + } + intLocalYield=parseInt(doc.illumina['Demultiplex_Stats']['Barcode_lane_statistics'][barcode]['Yield (Mbases)'].replace(/,/g, "")); + summary['yield']=summary['yield']+intLocalYield; + } + summary['yield']=summary['yield']/1000; + for (lane in undetermined){ + if (undetermined[lane]>1){ + /*if there is more than one undetermined indices, the actual yield is messed up, so we don't display it*/ + summary['yield']=0; + } + } + } + emit(doc["name"], summary); +} diff --git a/seed/views/flowcells/info/summary2.map.js b/seed/views/flowcells/info/summary2.map.js new file mode 100644 index 0000000..6bf18a2 --- /dev/null +++ b/seed/views/flowcells/info/summary2.map.js @@ -0,0 +1,91 @@ + +/* + Used by genomics-status at: + /api/v1/flowcell_info2, +*/ + +function ( doc) { + sum=Object(); + sum['name']=doc['name']; + if (doc['illumina'].hasOwnProperty('Summary')&& doc['RunInfo'].hasOwnProperty('Date')){ + sum['seqdone']=doc['RunInfo']['Date']; + if (doc['illumina']['Summary'].hasOwnProperty('read3')){ + //error rates per read and per lane + sum['err1']=Array(-1,0,0,0,0,0,0,0,0); + sum['err2']=Array(-1,0,0,0,0,0,0,0,0); + sum['err3']=Array(-1,0,0,0,0,0,0,0,0); + for(i=1;i<4;i++){ + for(lane in doc['illumina']['Summary']['read'+i]){ + sum['err'+i][lane]=doc['illumina']['Summary']['read'+i][lane]['ErrRatePhiX']; + } + } + } + } + if (doc['illumina'].hasOwnProperty('Demultiplex_Stats') && doc['illumina']['Demultiplex_Stats'].hasOwnProperty('Barcode_lane_statistics') && doc['illumina']['Demultiplex_Stats']['Barcode_lane_statistics'].length >0){ + sum['lane']=Object(); + //lanes are arrays of subsets + sum['lane']['1']=Array(); + sum['lane']['2']=Array(); + sum['lane']['3']=Array(); + sum['lane']['4']=Array(); + sum['lane']['5']=Array(); + sum['lane']['6']=Array(); + sum['lane']['7']=Array(); + sum['lane']['8']=Array(); + sum['yields']=Array(-1,0,0,0,0,0,0,0,0); + sum['seq_qc']=Array(-1,0,0,0,0,0,0,0,0); + sum['demuldone']=true; + subsets=[]; + plist=[]; + + for (lane in doc['illumina']['run_summary']){ + sum['seq_qc'][lane]=doc['illumina']['run_summary'][lane]['qc']; + } + + for (sample in doc['illumina']['Demultiplex_Stats']['Barcode_lane_statistics']){ + id=doc['illumina']['Demultiplex_Stats']['Barcode_lane_statistics'][sample]; + //if(id['Project']==='Undetermined_indices'){ + // continue; + //} + //subsets are sample objects" + Subset=Object(); + Subset['SampleName']=id['Sample ID']; + Subset['readsnb']=id['# Reads']; + proj_name = id['Project']; + plist.push(proj_name); + Subset['Project']=proj_name; + + lane = id['Lane']; + Subset['lane']=lane; + Subset['yield']=id['Yield (Mbases)']; + sum['yields'][lane]+=parseInt(id['Yield (Mbases)'].replace(",","")); + Subset['overthirty']=id['% of >= Q30 Bases (PF)']; + + Subset['barcode']=id['Index']; + Subset['desc']=id['Description']; + + if (doc.hasOwnProperty('lims_data') && doc.lims_data.run_summary[lane].hasOwnProperty('% phiX')){ + Subset['phix']=doc.lims_data.run_summary[lane]['% phiX']; + } + if (doc.hasOwnProperty('lims_data') && doc.lims_data.run_summary[lane].hasOwnProperty('% Error Rate R1')){ + var er_rate=doc.lims_data.run_summary[lane]['% Error Rate R1']; + if (doc.lims_data.run_summary[lane].hasOwnProperty('% Error Rate R2') && doc.lims_data.run_summary[lane]['% Error Rate R2'] != 0){ + er_rate=(er_rate+doc.lims_data.run_summary[lane]['% Error Rate R1'])/2; + } + Subset['er_rate']=er_rate; + } + subsets.push(Subset); + } + for (s in subsets){ + //order by lane + sum['lane'][subsets[s]['lane']].push(subsets[s]); + } + //clean duplicates + sum['plist']=plist.filter(function( item, index, inputArray ) { + return inputArray.indexOf(item) == index; + }); + + + } + emit(doc.name, sum) +} \ No newline at end of file diff --git a/seed/views/flowcells/instr/unmatched.map.js b/seed/views/flowcells/instr/unmatched.map.js new file mode 100644 index 0000000..c060e19 --- /dev/null +++ b/seed/views/flowcells/instr/unmatched.map.js @@ -0,0 +1,9 @@ +function(doc) { + var unmatched = [] + for (lane in doc["lanes"]) { + if (doc["lanes"][lane]["bc_metrics"]["unmatched"]) { + unmatched.push(doc["lanes"][lane]["bc_metrics"]["unmatched"]); + }; + }; + emit([doc["RunInfo"]["Date"], doc["RunInfo"]["Instrument"]], unmatched); +}; diff --git a/seed/views/flowcells/instrument/bp_yield.map.js b/seed/views/flowcells/instrument/bp_yield.map.js new file mode 100644 index 0000000..9562d8f --- /dev/null +++ b/seed/views/flowcells/instrument/bp_yield.map.js @@ -0,0 +1,14 @@ +/** + * Total yield per flowcell, based on Demultiplex counts, taking read length into account + */ +function(doc) { + tot = 0; + for (s in doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"]) { + y = doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"][s]["Yield (Mbases)"]; + if (y == null) { + y = "0"; + } + tot += parseInt(y.replace(",",""))*1e6; + } + emit([doc["RunParameters"]["RunMode"],doc["RunInfo"]["Date"],doc["RunInfo"]["Id"]],tot); +} diff --git a/seed/views/flowcells/instrument/clusters_raw.map.js b/seed/views/flowcells/instrument/clusters_raw.map.js new file mode 100644 index 0000000..d1a04ef --- /dev/null +++ b/seed/views/flowcells/instrument/clusters_raw.map.js @@ -0,0 +1,15 @@ +/* + Used by genomics-status at: + /api/v1/instrument_cluster_density, + /api/v1/instrument_cluster_density.png +*/ + +function(doc) { + var clusters = [] + for (lane in doc["illumina"]["Summary"]["read1"]) { + if (doc["illumina"]["Summary"]["read1"][lane]["ClustersRaw"]) { + clusters.push(+doc["illumina"]["Summary"]["read1"][lane]["ClustersRaw"]) + } + } + emit([doc["RunInfo"]["Date"], doc["RunInfo"]["Instrument"]], clusters); +} diff --git a/seed/views/flowcells/instrument/error_rates.map.js b/seed/views/flowcells/instrument/error_rates.map.js new file mode 100644 index 0000000..d732f50 --- /dev/null +++ b/seed/views/flowcells/instrument/error_rates.map.js @@ -0,0 +1,17 @@ +/* + Used by genomics-status at: + /api/v1/instrument_error_rates + /api/v1/instrument_error_rates.png +*/ + +function(doc) { + var error_rates = []; + for (lane in doc["lanes"]) { + for (read in doc["RunInfo"]["Reads"]) { + if (doc["RunInfo"]["Reads"][read]["IsIndexedRead"] === "N") { + error_rates.push(+doc["illumina"]["Summary"]["read" + doc["RunInfo"]["Reads"][read]["Number"]][lane]["ErrRatePhiX"]); + }; + }; + }; + emit([doc["RunInfo"]["Date"], doc["RunInfo"]["Instrument"]], error_rates); +}; diff --git a/seed/views/flowcells/instrument/unmatched.map.js b/seed/views/flowcells/instrument/unmatched.map.js new file mode 100644 index 0000000..c4b4a37 --- /dev/null +++ b/seed/views/flowcells/instrument/unmatched.map.js @@ -0,0 +1,15 @@ +/* + Used by genomics-status at: + /api/v1/instrument_unmatched, + /api/v1/instrument_unmatched.png +*/ + +function(doc) { + var unmatched = [] + for (lane in doc["lanes"]) { + if (doc["lanes"][lane]["bc_metrics"]["unmatched"]) { + unmatched.push(doc["lanes"][lane]["bc_metrics"]["unmatched"]); + }; + }; + emit([doc["RunInfo"]["Date"], doc["RunInfo"]["Instrument"]], unmatched); +}; diff --git a/seed/views/flowcells/instrument/yield.map.js b/seed/views/flowcells/instrument/yield.map.js new file mode 100644 index 0000000..cd0411a --- /dev/null +++ b/seed/views/flowcells/instrument/yield.map.js @@ -0,0 +1,21 @@ +/* + Used by genomics-status at: + /api/v1/instrument_yield, + /api/v1/instrument_yield.png +*/ + +function(doc) { + var yields = [] + for (lane in doc["lanes"]) { + if (doc["illumina"]["Demultiplex_Stats"] !== undefined) { + var yield = 0 + for (sample in doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"]) { + if (doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"][sample]["Lane"] === lane) { + yield += 0.5*doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"][sample]["# Reads"].replace(/,/g,"") + }; + }; + }; + yields.push(yield) + }; + emit([doc["RunInfo"]["Date"], doc["RunInfo"]["Instrument"]], yields); +}; diff --git a/seed/views/flowcells/lanes/bp_yield.map.js b/seed/views/flowcells/lanes/bp_yield.map.js new file mode 100644 index 0000000..7c18591 --- /dev/null +++ b/seed/views/flowcells/lanes/bp_yield.map.js @@ -0,0 +1,27 @@ +/** + * Total yield per lane, takes the read length into account + */ +function(doc) { + nreads = 0 + for (r in doc["RunInfo"]["Reads"]) { + if (doc["RunInfo"]["Reads"][r]["IsIndexedRead"] === "N") { + nreads += 1; + } + } + var lanes = doc["illumina"]["run_summary"]; + for (l in lanes) { + lane_yield = 0; + for (var r=1; r<=nreads; r++) { + y = doc["illumina"]["run_summary"][l]["Yield PF (Gb) R" + r.toString()]; + if (y == null) { + y = 0; + } + lane_yield += y; + } + var mode = doc["RunParameters"]["RunMode"]; + if(mode == null && doc["RunParameters"]["SampleSheetFolder"].indexOf("MiSeq") != -1) { + mode = "MiSeq"; + } + emit([mode, doc["RunInfo"]["Id"], l],lane_yield*1e9); + } +} diff --git a/seed/views/flowcells/lanes/cluster_cont.map.js b/seed/views/flowcells/lanes/cluster_cont.map.js new file mode 100644 index 0000000..271a91e --- /dev/null +++ b/seed/views/flowcells/lanes/cluster_cont.map.js @@ -0,0 +1,7 @@ +function(doc) { + for (lane in doc["illumina"]["Summary"]["read1"]) { + if (doc["illumina"]["Summary"]["read1"][lane]["ClustersRaw"]) { + emit([doc["name"],lane], {"clusters_raw": doc["illumina"]["Summary"]["read1"][lane]["ClustersRaw"], "clusters_pf": doc["illumina"]["Summary"]["read1"][lane]["ClustersPF"]}); + } + } +} diff --git a/seed/views/flowcells/lanes/cluster_count.map.js b/seed/views/flowcells/lanes/cluster_count.map.js new file mode 100644 index 0000000..271a91e --- /dev/null +++ b/seed/views/flowcells/lanes/cluster_count.map.js @@ -0,0 +1,7 @@ +function(doc) { + for (lane in doc["illumina"]["Summary"]["read1"]) { + if (doc["illumina"]["Summary"]["read1"][lane]["ClustersRaw"]) { + emit([doc["name"],lane], {"clusters_raw": doc["illumina"]["Summary"]["read1"][lane]["ClustersRaw"], "clusters_pf": doc["illumina"]["Summary"]["read1"][lane]["ClustersPF"]}); + } + } +} diff --git a/seed/views/flowcells/lanes/clusters.map.js b/seed/views/flowcells/lanes/clusters.map.js new file mode 100644 index 0000000..9123a64 --- /dev/null +++ b/seed/views/flowcells/lanes/clusters.map.js @@ -0,0 +1,17 @@ +/* + Used by genomics-status at: + /api/v1/plot/clusters_per_lane.png +*/ + +function(doc) { + for (lane in doc.illumina.run_summary) { + var data ={}; + + data['filtered_clusters']=doc.illumina.run_summary[lane]['Clusters PF R1']; + data['unfiltered_clusters']=doc.illumina.run_summary[lane]['Clusters Raw R1']; + + + emit([doc["name"], lane], data); + + }; +}; \ No newline at end of file diff --git a/seed/views/flowcells/lanes/date_pf.map.js b/seed/views/flowcells/lanes/date_pf.map.js new file mode 100644 index 0000000..8fc28d8 --- /dev/null +++ b/seed/views/flowcells/lanes/date_pf.map.js @@ -0,0 +1,35 @@ +/** + * reads/per_lane + */ +function(doc) { +// var lanes = doc["illumina"]["run_summary"]; + var num_lanes = 0; +// for (l in lanes) { +// num_lanes++; +// } + + var date = doc["RunParameters"]["RunStartDate"]; + var mode = doc["RunParameters"]["RunMode"]; + if(mode == null && doc["RunParameters"]["SampleSheetFolder"].indexOf("MiSeq") != -1) { + mode = "MiSeq"; + } + if (mode == "HighOutput") { + num_lanes = 8; + } else if (mode == "RapidRun") { + num_lanes = 2; + } else if (mode == "MiSeq") { + num_lanes = 1; + } + emit([date, mode, doc["RunInfo"]["Id"]],num_lanes); +// emit([date, mode, doc["RunInfo"]["Id"]],lanes); + +// for (l in lanes) { +// var reads = doc["illumina"]["run_summary"][l]["Clusters PF R1"]; +// var mode = doc["RunParameters"]["RunMode"]; +// if(mode == null && doc["RunParameters"]["SampleSheetFolder"].indexOf("MiSeq") != -1) { +// mode = "MiSeq"; +// } +// emit([mode, doc["RunInfo"]["Id"], l],reads); +// } + +} diff --git a/seed/views/flowcells/lanes/date_pf.reduce.js b/seed/views/flowcells/lanes/date_pf.reduce.js new file mode 100644 index 0000000..a105062 --- /dev/null +++ b/seed/views/flowcells/lanes/date_pf.reduce.js @@ -0,0 +1 @@ +_sum diff --git a/seed/views/flowcells/lanes/demultiplex.map.js b/seed/views/flowcells/lanes/demultiplex.map.js new file mode 100644 index 0000000..3c063bf --- /dev/null +++ b/seed/views/flowcells/lanes/demultiplex.map.js @@ -0,0 +1,26 @@ +/* + Used by genomics-status at: + /api/v1/flowcell_demultiplex/:id, + /api/v1/plot/reads_per_lane.png +*/ + +function(doc) { + for (lane in doc["lanes"]) { + var demultiplex = Object() + var bc_metrics = doc["lanes"][lane]["bc_metrics"] + + matched = 0 + for (index in bc_metrics) { + if (index != "unmatched") { + matched += bc_metrics[index]; + } + } + + demultiplex["matched"] = matched; + demultiplex["yield"] = matched + bc_metrics["unmatched"]; + demultiplex["demultiplexed"] = demultiplex["matched"] / demultiplex["yield"]; + + emit([doc["name"], lane], demultiplex); + + }; +}; diff --git a/seed/views/flowcells/lanes/err_rate_phix_yield.map.js b/seed/views/flowcells/lanes/err_rate_phix_yield.map.js new file mode 100644 index 0000000..5f86fa8 --- /dev/null +++ b/seed/views/flowcells/lanes/err_rate_phix_yield.map.js @@ -0,0 +1,27 @@ +/* + Used by genomics-status at: + /api/v1/phix_err_rate +*/ + +function(doc) { + for (lane in doc["lanes"]) { + var sum = 0; + var count = 0; + var yield = null; + for (read in doc["RunInfo"]["Reads"]) { + if (doc["RunInfo"]["Reads"][read]["IsIndexedRead"] === "N") { + sum += 1*doc["illumina"]["Summary"]["read" + doc["RunInfo"]["Reads"][read]["Number"]][lane]["ErrRatePhiX"]; + count++; + }; + }; + if (doc["illumina"]["Demultiplex_Stats"] !== undefined) { + yield = 0 + for (sample in doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"]) { + if (doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"][sample]["Lane"] === lane) { + yield += 0.5*doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"][sample]["# Reads"].replace(/,/g,"") + } + } + }; + emit([doc["name"], lane], {"err_rate_phix": (sum/count), "yield": yield}); + }; +}; diff --git a/seed/views/flowcells/lanes/gtq30.map.js b/seed/views/flowcells/lanes/gtq30.map.js new file mode 100644 index 0000000..e63d493 --- /dev/null +++ b/seed/views/flowcells/lanes/gtq30.map.js @@ -0,0 +1,25 @@ +/* + Used by genomics-status at: + /api/v1/flowcell_q30/:id, + /api/v1/plot/q30.png +*/ + +function(doc) { + var stats = doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"]; + var instrument = doc["RunInfo"]["Instrument"] + var runmode = doc["RunParameters"]["RunMode"] + + var setup = []; + for (read in doc["RunInfo"]["Reads"]) { + if (doc["RunInfo"]["Reads"][read]["IsIndexedRead"] === "N") { + setup.push(+doc["RunInfo"]["Reads"][read]["NumCycles"]); + } + } + + for (sample in stats) { + var q30 = stats[sample]["% of >= Q30 Bases (PF)"]; + + emit([doc["name"], runmode, stats[sample]["Lane"], stats[sample]["Index"]], + {"sum": +q30, "count": 1, "instrument": instrument, "setup": setup}); + }; +}; diff --git a/seed/views/flowcells/lanes/gtq30.reduce.js b/seed/views/flowcells/lanes/gtq30.reduce.js new file mode 100644 index 0000000..60d1a75 --- /dev/null +++ b/seed/views/flowcells/lanes/gtq30.reduce.js @@ -0,0 +1,13 @@ +function (key, values, rereduce) { + var result = {'sum': 0, 'count': 0, 'instrument': null, 'setup': null} + + for (v in values) { + result['count'] += values[v]['count'] || 0 + result['sum'] += values[v]['sum'] || 0 + result['instrument'] = values[v]['instrument'] + result['setup'] = values[v]['setup'] + } + + return result + +} diff --git a/seed/views/flowcells/lanes/gtq30_old.map.js b/seed/views/flowcells/lanes/gtq30_old.map.js new file mode 100644 index 0000000..d718ba6 --- /dev/null +++ b/seed/views/flowcells/lanes/gtq30_old.map.js @@ -0,0 +1,21 @@ +// Used by: genomics-status.scilifelab.se/q30 + +function(doc) { + var stats = doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"]; + var instrument = doc["RunInfo"]["Instrument"] + var runmode = doc["RunParameters"]["RunMode"] + + var setup = []; + for (read in doc["RunInfo"]["Reads"]) { + if (doc["RunInfo"]["Reads"][read]["IsIndexedRead"] === "N") { + setup.push(+doc["RunInfo"]["Reads"][read]["NumCycles"]); + } + } + + for (sample in stats) { + var q30 = stats[sample]["% of >= Q30 Bases (PF)"]; + + emit([doc["name"], stats[sample]["Lane"], stats[sample]["Index"]], + {"sum": +q30, "count": 1, "instrument": instrument, "setup": setup}); + }; +}; \ No newline at end of file diff --git a/seed/views/flowcells/lanes/gtq30_old.reduce.js b/seed/views/flowcells/lanes/gtq30_old.reduce.js new file mode 100644 index 0000000..60d1a75 --- /dev/null +++ b/seed/views/flowcells/lanes/gtq30_old.reduce.js @@ -0,0 +1,13 @@ +function (key, values, rereduce) { + var result = {'sum': 0, 'count': 0, 'instrument': null, 'setup': null} + + for (v in values) { + result['count'] += values[v]['count'] || 0 + result['sum'] += values[v]['sum'] || 0 + result['instrument'] = values[v]['instrument'] + result['setup'] = values[v]['setup'] + } + + return result + +} diff --git a/seed/views/flowcells/lanes/project_lane_undemultiplex.map.js b/seed/views/flowcells/lanes/project_lane_undemultiplex.map.js new file mode 100644 index 0000000..8f3a252 --- /dev/null +++ b/seed/views/flowcells/lanes/project_lane_undemultiplex.map.js @@ -0,0 +1,33 @@ +function(doc) { + var projects = {}; + var total = {}; + var undemux = {}; + var index = {}; + if ("Demultiplex_Stats" in doc["illumina"]) { + + for (sample in doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"]) { + lane = doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"][sample]["Lane"]; + proj = doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"][sample]["Project"].replace("__","."); + idx = doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"][sample]["Index"].replace("-",""); + count = parseInt(doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"][sample]["# Reads"].replace(",","")); + + if (!(lane in total)) { + total[lane] = 0; + projects[lane] = {}; + index[lane] = {}; + } + +      total[lane] += count; + if (proj == "Undetermined_indices") { + undemux[lane] = count; + } + else { + projects[lane][proj] = 1; + index[lane][idx.length.toString()] = idx.length; + } + } + for (var lane in total) { + emit([Object.keys(projects[lane]).join(),doc["name"],lane],{"index_length": Object.keys(index[lane]).join(), "fraction_undemultiplexed": undemux[lane]/total[lane]}); + } + } +}; diff --git a/seed/views/flowcells/lanes/projects.map.js b/seed/views/flowcells/lanes/projects.map.js new file mode 100644 index 0000000..2f3b22f --- /dev/null +++ b/seed/views/flowcells/lanes/projects.map.js @@ -0,0 +1,18 @@ +function(doc) { + lane_projs = Object() + for (sample in doc["samplesheet_csv"]){ + sample_id = doc["samplesheet_csv"][sample]["SampleID"] + proj_id = sample_id.split("_")[0] + lane = doc["samplesheet_csv"][sample]["Lane"] + if (typeof(lane_projs[lane]) === 'undefined'){ + lane_projs[lane] = [] + } + if (lane_projs[lane].indexOf(proj_id) === -1){ + lane_projs[lane].push(proj_id) + } + } + + for (lane in lane_projs){ + emit([doc["name"], lane], lane_projs[lane]) + } +} diff --git a/seed/views/flowcells/lanes/qc.map.js b/seed/views/flowcells/lanes/qc.map.js new file mode 100644 index 0000000..1cd1892 --- /dev/null +++ b/seed/views/flowcells/lanes/qc.map.js @@ -0,0 +1,15 @@ +/* + Used by genomics-status at: + /api/v1/flowcell_qc/:id +*/ + +function(doc) { + for (lane in doc["lanes"]) { + + var r1 = doc["illumina"]["Summary"]["read1"][lane]; + var r3 = doc["illumina"]["Summary"]["read3"][lane]; + + emit([doc["name"], lane], {"read1": r1, "read3": r3}); + + }; +}; diff --git a/seed/views/flowcells/lanes/qtq30_old.map.js b/seed/views/flowcells/lanes/qtq30_old.map.js new file mode 100644 index 0000000..7cb4ec8 --- /dev/null +++ b/seed/views/flowcells/lanes/qtq30_old.map.js @@ -0,0 +1,21 @@ +// Used by: genomics-status.scilifelab.se/q30 + +function(doc) { + var stats = doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"]; + var instrument = doc["RunInfo"]["Instrument"] + var runmode = doc["RunParameters"]["RunMode"] + + var setup = []; + for (read in doc["RunInfo"]["Reads"]) { + if (doc["RunInfo"]["Reads"][read]["IsIndexedRead"] === "N") { + setup.push(+doc["RunInfo"]["Reads"][read]["NumCycles"]); + } + } + + for (sample in stats) { + var q30 = stats[sample]["% of >= Q30 Bases (PF)"]; + + emit([doc["name"], stats[sample]["Lane"], stats[sample]["Index"]], + {"sum": +q30, "count": 1, "instrument": instrument, "setup": setup}); + }; +}; diff --git a/seed/views/flowcells/lanes/unmatched.map.js b/seed/views/flowcells/lanes/unmatched.map.js new file mode 100644 index 0000000..0edff71 --- /dev/null +++ b/seed/views/flowcells/lanes/unmatched.map.js @@ -0,0 +1,13 @@ +/* + Used by genomics-status at: + /api/v1/expected + /api/v1/plot/barcodes_vs_expected.png +*/ + +function(doc) { + for (lane in doc["lanes"]) { + if (doc["lanes"][lane]["bc_metrics"]["unmatched"]) { + emit([doc["name"].substr(7), lane], doc["lanes"][lane]["bc_metrics"]["unmatched"]); + }; + }; +}; diff --git a/seed/views/flowcells/lanes/unmatched.reduce.js b/seed/views/flowcells/lanes/unmatched.reduce.js new file mode 100644 index 0000000..a105062 --- /dev/null +++ b/seed/views/flowcells/lanes/unmatched.reduce.js @@ -0,0 +1 @@ +_sum diff --git a/seed/views/flowcells/lims/summary.map.js b/seed/views/flowcells/lims/summary.map.js new file mode 100644 index 0000000..092167e --- /dev/null +++ b/seed/views/flowcells/lims/summary.map.js @@ -0,0 +1,9 @@ +function(doc) { + if (doc.hasOwnProperty('lims_data')){ + data={}; + data['step_id']=doc.lims_data.step_id; + data['container_id']=doc.lims_data.container_id; + data['container_name']=doc.lims_data.container_name; + emit(doc.name, data); +} +} \ No newline at end of file diff --git a/seed/views/flowcells/names/Barcode_lane_stat.map.js b/seed/views/flowcells/names/Barcode_lane_stat.map.js new file mode 100644 index 0000000..013e8c4 --- /dev/null +++ b/seed/views/flowcells/names/Barcode_lane_stat.map.js @@ -0,0 +1,3 @@ +function(doc) { + emit(doc["name"],doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"] ); +} diff --git a/seed/views/flowcells/names/id_to_name.map.js b/seed/views/flowcells/names/id_to_name.map.js new file mode 100644 index 0000000..cdc11c8 --- /dev/null +++ b/seed/views/flowcells/names/id_to_name.map.js @@ -0,0 +1,3 @@ +function(doc) { + emit(doc["_id"], doc["name"]); +} diff --git a/seed/views/flowcells/names/name.map.js b/seed/views/flowcells/names/name.map.js new file mode 100644 index 0000000..f113de1 --- /dev/null +++ b/seed/views/flowcells/names/name.map.js @@ -0,0 +1,3 @@ +function(doc) { + emit(doc["name"], null); +} diff --git a/seed/views/flowcells/names/name.reduce.js b/seed/views/flowcells/names/name.reduce.js new file mode 100644 index 0000000..768b109 --- /dev/null +++ b/seed/views/flowcells/names/name.reduce.js @@ -0,0 +1 @@ +_count \ No newline at end of file diff --git a/seed/views/flowcells/names/project_ids_list.map.js b/seed/views/flowcells/names/project_ids_list.map.js new file mode 100644 index 0000000..98ac5be --- /dev/null +++ b/seed/views/flowcells/names/project_ids_list.map.js @@ -0,0 +1,8 @@ +function(doc) { + var proj_in_fc = {} + for (sample in doc["samplesheet_csv"]){ + var proj_id = doc["samplesheet_csv"][sample]["SampleID"].split("_")[0] + proj_in_fc[proj_id] = true + } + emit(doc["name"], Object.keys(proj_in_fc)) +} diff --git a/seed/views/flowcells/reads/per_lane.map.js b/seed/views/flowcells/reads/per_lane.map.js new file mode 100644 index 0000000..b5bc270 --- /dev/null +++ b/seed/views/flowcells/reads/per_lane.map.js @@ -0,0 +1,14 @@ +/** + * reads/per_lane + */ +function(doc) { + var lanes = doc["illumina"]["run_summary"]; + for (l in lanes) { + var reads = doc["illumina"]["run_summary"][l]["Clusters PF R1"]; + var mode = doc["RunParameters"]["RunMode"]; + if(mode == null && doc["RunParameters"]["SampleSheetFolder"].indexOf("MiSeq") != -1) { + mode = "MiSeq"; + } + emit([mode, doc["RunInfo"]["Id"], l],reads); + } +} diff --git a/seed/views/flowcells/samples/demultiplex.map.js b/seed/views/flowcells/samples/demultiplex.map.js new file mode 100644 index 0000000..048b688 --- /dev/null +++ b/seed/views/flowcells/samples/demultiplex.map.js @@ -0,0 +1,11 @@ +function(doc) { + var stats = doc["illumina"]["Demultiplex_Stats"]["Barcode_lane_statistics"]; + for (sample in stats) { + var stat = Object(); + stat["sample"] = stats[sample]; + stat["instrument"] = doc["RunInfo"]["Instrument"]; + stat["setup"] = doc["RunInfo"]["Reads"]; + + emit([doc["name"], stat["sample"]["Lane"], stat["sample"]["Index"]], stat); + }; +}; diff --git a/seed/views/flowcells/samples/lane_clusters.map.js b/seed/views/flowcells/samples/lane_clusters.map.js new file mode 100644 index 0000000..2fbc1e8 --- /dev/null +++ b/seed/views/flowcells/samples/lane_clusters.map.js @@ -0,0 +1,23 @@ +function(doc) { + var key=''; + var vk = ''; + var obj={}; + var cl=0; + if ('illumina' in doc && 'Demultiplex_Stats' in doc['illumina'] && 'Barcode_lane_statistics' in doc['illumina']['Demultiplex_Stats']){ + for (barcode in doc['illumina']['Demultiplex_Stats']['Barcode_lane_statistics']){ + key=doc['illumina']['Demultiplex_Stats']['Barcode_lane_statistics'][barcode]['Sample ID']; + if (key.indexOf("Sample_")!= -1){ + key=key.substr(7); + } + vk=doc['RunInfo']['Id']+':'+doc['illumina']['Demultiplex_Stats']['Barcode_lane_statistics'][barcode]['Lane']; + cl=parseInt(doc['illumina']['Demultiplex_Stats']['Barcode_lane_statistics'][barcode]['# Reads'].replace(/,/g,'')); + q30=parseFloat(doc['illumina']['Demultiplex_Stats']['Barcode_lane_statistics'][barcode]['% of >= Q30 Bases (PF)']); + obj={fcp: vk,cl : cl,q30 : q30}; + + if (['', 'Undetermined', 'unknown'].indexOf(key)== -1){ + emit(key, obj); + } + } + } + +} \ No newline at end of file diff --git a/seed/views/flowcells/time/dates.map.js b/seed/views/flowcells/time/dates.map.js new file mode 100644 index 0000000..cd57d51 --- /dev/null +++ b/seed/views/flowcells/time/dates.map.js @@ -0,0 +1,5 @@ +function(doc) { + var date_name = doc["name"].split("_"); + var d = date_name[0]; + emit([d.substr(0,2), d.substr(2,2), d.substr(4,2)], doc["name"]); +} diff --git a/seed/views/flowcells/time/dates.reduce.js b/seed/views/flowcells/time/dates.reduce.js new file mode 100644 index 0000000..768b109 --- /dev/null +++ b/seed/views/flowcells/time/dates.reduce.js @@ -0,0 +1 @@ +_count \ No newline at end of file diff --git a/seed/views/flowcells/time/last_updated.map.js b/seed/views/flowcells/time/last_updated.map.js new file mode 100644 index 0000000..56bc678 --- /dev/null +++ b/seed/views/flowcells/time/last_updated.map.js @@ -0,0 +1,8 @@ +/* + Used by genomics-status at: + /api/v1/last_updated +*/ + +function(doc) { + emit(doc['modification_time'], doc['name']); +}