Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into 18-parsing-csv-file-w…
Browse files Browse the repository at this point in the history
…ith-only-one-column-fails
  • Loading branch information
roschro committed Jan 26, 2024
2 parents 8ab730f + 784f4fa commit e0aa804
Show file tree
Hide file tree
Showing 20 changed files with 331 additions and 236 deletions.
File renamed without changes.
10 changes: 10 additions & 0 deletions src/lib/components/general/BackButton.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script>
import { base } from "$app/paths";
export let parentRoute = "";
</script>

<a href="{base}/{parentRoute}" type="button" class="btn variant-filled-secondary mb-6 print:hidden ml-[10mm] mt-[10mm]">
<span class="material-symbols-outlined">arrow_back</span>
<span>Go Back</span>
</a>
File renamed without changes.
38 changes: 38 additions & 0 deletions src/lib/components/postprocessing/CsvDownload.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script>
export let downloadEnabled = false;
export let csvData = "";
function downloadCsv(){
const filename = 'study_results.csv';
const blob = new Blob([csvData], { type: 'text/csv' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
</script>

<div class="container h-full mx-auto flex justify-center items-center text-center">
<div class="w-1/2 space-y-6 my-6">
<section class="w-full p-4 space-y-4">
{#if downloadEnabled}
<p>Processing finished!</p>
{:else}
<p>Files are being processed...</p>
{/if}
</section>
<section class="w-full flex justify-center items-center">
<button on:click={downloadCsv} type="button" class="btn variant-filled-primary p-6 mt-6" disabled={!downloadEnabled}>
<span class="material-symbols-outlined">download</span>
<span>Download CSV</span>
</button>
</section>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<script lang="ts">
import { collectData, dataToWideFormat } from '$lib/postprocessing/logCleaning';
import { extractZip, getDateFromFileName, getSubjectFromFileName, objectIsEmpty } from '$lib/postprocessing/utils';
import { FileDropzone } from '@skeletonlabs/skeleton';
import { FileDropzone, toastStore, type ToastSettings, Toast } from '@skeletonlabs/skeleton';
import Papa from 'papaparse';
import SelectedFileList from './SelectedFileList.svelte';
export let files: FileList = <FileList>{};
export let filesUploaded: boolean = false;
Expand All @@ -18,10 +19,7 @@
function handleSubmit() {
filesSubmitted = true;
extractZip(files).then((data) => {
console.log(data);
// TODO: filename sanity check
let result = data.map((file: { name: string, data: any[] }) => {
console.log(file.name);
let date = getDateFromFileName(file.name);
let subject = getSubjectFromFileName(file.name);
let info = collectData(file.data);
Expand All @@ -30,15 +28,21 @@
.filter((entry) => !objectIsEmpty(entry.info));
let csvArray = dataToWideFormat(result);
csvData = Papa.unparse(csvArray);
console.log("unparsed: " + csvData);
downloadEnabled = true;
}).catch((err) => {
console.log(err);
const t: ToastSettings = {
message: 'An error occurred while processing your data:<br>' + err + '<br>Please make sure you uploaded the correct file(s) and try again.',
autohide: false,
};
toastStore.trigger(t);
filesSubmitted = false;
filesUploaded = false;
});
}
</script>

<Toast />
<form class="container h-full mx-auto flex justify-center items-center" on:submit|preventDefault={handleSubmit}>
<div class="w-1/2 space-y-6 my-6">
<FileDropzone
Expand All @@ -55,23 +59,8 @@
<svelte:fragment slot="message"><b>Upload files</b> or drag and drop.</svelte:fragment>
<svelte:fragment slot="meta">Select all participant ZIP-files to evaluate.</svelte:fragment>
</FileDropzone>
<section class="w-full text-token card p-4 space-y-4">
{#if files.length > 0}
<p class="font-bold">Selected files</p>
<ul class="list">
{#each { length: files.length } as _, i}
<li>
<span class="badge-icon p-4 variant-soft-tertiary">
<span class="material-symbols-outlined"> contact_page </span>
</span>
<span class="flex-auto">{files[i].name}</span>
</li>
{/each}
</ul>
{:else}
<p class="font-bold text-center">No files selected.</p>
{/if}
</section>

<SelectedFileList bind:files={files} />
<section class="w-full flex justify-end items-end">
<button type="submit" class="btn variant-filled-primary p-2" disabled={!filesUploaded}>
<span>Start Processing</span>
Expand Down
21 changes: 21 additions & 0 deletions src/lib/components/postprocessing/SelectedFileList.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script lang="ts">
export let files: FileList = <FileList>{};
</script>

<section class="w-full text-token card p-4 space-y-4">
{#if files.length > 0}
<p class="font-bold">Selected files</p>
<ul class="list">
{#each { length: files.length } as _, i}
<li>
<span class="badge-icon p-4 variant-soft-tertiary">
<span class="material-symbols-outlined"> contact_page </span>
</span>
<span class="flex-auto">{files[i].name}</span>
</li>
{/each}
</ul>
{:else}
<p class="font-bold text-center">No files selected.</p>
{/if}
</section>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { barcodeProps, barcodePropsValid, studyProps} from "$lib/configStore";
import { barcodeProps, barcodePropsValid, studyProps} from "$lib/stores/configStore";
import { Step } from "@skeletonlabs/skeleton";
import { onMount, afterUpdate } from "svelte";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import { CAR_STUDY, DEFAULT_SALIVA_DISTANCE, OTHER_STUDY } from '$lib/constants';
import { studyProps, qrCodeProps, qrCodePropsValid } from '$lib/configStore';
import { studyProps, qrCodeProps, qrCodePropsValid } from '$lib/stores/configStore';
import { Step } from '@skeletonlabs/skeleton';
import { onMount, afterUpdate } from 'svelte';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { studyProps, studyPropsValid } from '$lib/configStore';
import { studyProps, studyPropsValid } from '$lib/stores/configStore';
import { CAR_STUDY, LAB_STUDY, OTHER_STUDY } from '$lib/constants';
import { FileDropzone, Step, Toast, type ToastSettings } from '@skeletonlabs/skeleton';
import { onMount } from 'svelte';
Expand Down Expand Up @@ -41,7 +41,6 @@
for(let id of list) {
let element = document.getElementById(id);
if(element instanceof HTMLInputElement){
//console.log(id);
if(!(element.reportValidity())){
return false;
}
Expand Down
14 changes: 14 additions & 0 deletions src/lib/postprocessing/logCleaning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ const SAMPLING_COUNT = "sample_count";
const SALIVA_ID = "saliva_id";

export function collectData(dayData: Array<any>): { [key: string]: any } {
// collect awakening and sampling info
// scan dayData for awakening and sampling info and return object containing of the extracted respective info
let result: { [key: string]: any } = {};
let awakening = extractAwakeningInfo(dayData);
let sampling = extractSamplingTimes(dayData);
Expand All @@ -28,6 +30,8 @@ export function collectData(dayData: Array<any>): { [key: string]: any } {
}

export function extractAwakeningInfo(dayData: Array<any>) {
// return object with properties awakening time and type
// returns empty object if no suitable information contained in dayData
let data = extractData(dayData, Object.keys(PROP_AWAKENING_TYPES));
let result: { [key: string]: any } = {};
if (data.length > 0) {
Expand All @@ -42,6 +46,8 @@ export function extractAwakeningInfo(dayData: Array<any>) {
}

export function extractSamplingTimes(dayData: Array<any>) {
// return result object with properties sampling time and sample id and total number of samples in dayData
// returns empty object if no suitable information contained in dayData
let samples = extractData(dayData, PROP_SAMPLING_TIME);
let result: { [key: string]: any } = {};
if (samples.length > 0) {
Expand All @@ -67,6 +73,8 @@ export function extractSamplingTimes(dayData: Array<any>) {
}

export function dataToWideFormat(data: Array<any>): Array<any> {
// transform collected data to pandas-style wide format
// contains all days and samples per day in columns and all subjects in rows
let csvArray = [];

// create header of csv file
Expand All @@ -85,6 +93,7 @@ export function dataToWideFormat(data: Array<any>): Array<any> {
}

function extractData(dayData: Array<any>, key: (string | string[])): Array<any> {
// extract data from dayData that matches key
let result = [];
if (typeof key === "string") {
result = dayData.filter(entry => entry[1] === key);
Expand Down Expand Up @@ -117,6 +126,8 @@ function getMaxNumberOfDays(data: Array<any>): number {
}

function getMaxNumberOfSamples(data: Array<any>): { maxCount: number, saliva_ids: Array<any> } {
// get maximum number of samples per day from all subjects
// extract the corresponding saliva ids and use them as a reference
let maxCount = 0;
let saliva_ids: Array<any> = []
data.forEach(entry => {
Expand All @@ -130,6 +141,7 @@ function getMaxNumberOfSamples(data: Array<any>): { maxCount: number, saliva_ids
}

function createHeader(dayCount: number, samples: Array<any>): Array<string> {
// create header for csv file
let header: Array<string> = [];
header.push("subject");
for (let i = 1; i <= dayCount; i++) {
Expand All @@ -144,6 +156,7 @@ function createHeader(dayCount: number, samples: Array<any>): Array<string> {
}

function extractUniqueSubjects(data: Array<any>) {
// extract unique subject ids from data
let subjectArray: Array<string> = [];
data.forEach(entry => {
if (!subjectArray.includes(entry.subject)) {
Expand All @@ -154,6 +167,7 @@ function extractUniqueSubjects(data: Array<any>) {
}

function createSubjectRow(subject: string, data: Array<any>, saliva_ids: Array<any>) {
// concatenate all data for one subject in one row for the final csv array
let row: Array<string> = [];
row.push(subject);
const relevantEntries = data.filter(entry => entry.subject === subject);
Expand Down
Loading

0 comments on commit e0aa804

Please sign in to comment.