Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Conversion Progress Bars #778

Merged
merged 36 commits into from
Jun 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
d128c6a
Attempt parallel conversion
garrettmflynn May 13, 2024
4c452f9
Add global conversion progress bar
garrettmflynn May 13, 2024
0d3935d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 13, 2024
6af1327
Merge branch 'main' into hdmf-progress-bars
CodyCBakerPhD May 15, 2024
835126b
Update manage_neuroconv.py
garrettmflynn May 15, 2024
511ca60
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 15, 2024
fd741e9
Working conversion updates from HDMF using new PRs across different d…
garrettmflynn May 15, 2024
341d09a
Merge branch 'hdmf-progress-bars' of https://github.com/NeurodataWith…
garrettmflynn May 15, 2024
448f47d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 15, 2024
46b1626
Show incorrect progress but do not render
garrettmflynn May 15, 2024
aa4dd0c
Merge branch 'hdmf-progress-bars' of https://github.com/NeurodataWith…
garrettmflynn May 15, 2024
499c2c0
Pass errors from individual processes to a run-specific log file in t…
garrettmflynn May 15, 2024
128e053
Merge branch 'main' into hdmf-progress-bars
garrettmflynn May 15, 2024
c4a48a2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 15, 2024
e8f11ff
Merge branch 'main' into hdmf-progress-bars
CodyCBakerPhD May 17, 2024
1aff868
Merge branch 'main' into hdmf-progress-bars
garrettmflynn May 20, 2024
885e1e0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 20, 2024
9d07e51
Merge branch 'save-logs' into hdmf-progress-bars
CodyCBakerPhD May 20, 2024
531476b
Merge branch 'main' into hdmf-progress-bars
CodyCBakerPhD May 21, 2024
d2bcf7e
Merge branch 'main' into hdmf-progress-bars
garrettmflynn May 30, 2024
b42cc0a
Update neuroconv.py
garrettmflynn May 30, 2024
dcf1815
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 30, 2024
5fff872
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 30, 2024
07c8d00
Update GuidedInspectorPage.js
garrettmflynn May 31, 2024
4e07964
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 31, 2024
837b71d
Update pipelines.test.ts
garrettmflynn May 31, 2024
3234e76
Update pipelines.test.ts
garrettmflynn May 31, 2024
7576a77
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 31, 2024
8febb0e
Update synced data check and awaiting screenshot
garrettmflynn May 31, 2024
559a633
Merge branch 'hdmf-progress-bars' of https://github.com/NeurodataWith…
garrettmflynn May 31, 2024
54ea4c9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 31, 2024
cbf6343
Take screenshots during long-running events
garrettmflynn May 31, 2024
8f4cba3
Merge branch 'hdmf-progress-bars' of https://github.com/NeurodataWith…
garrettmflynn May 31, 2024
1753aac
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 31, 2024
a5a7a88
Merge branch 'main' into hdmf-progress-bars
CodyCBakerPhD Jun 1, 2024
16c5307
Merge branch 'main' into hdmf-progress-bars
CodyCBakerPhD Jun 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/electron/frontend/core/components/ProgressBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,10 @@ export class ProgressBar extends LitElement {

render() {

const percent = this.format.total ? 100 * (this.format.n / this.format.total) : 0;
const remaining = this.format.rate && this.format.total ? (this.format.total - this.format.n) / this.format.rate : 0; // Seconds
const n = this.format.n > this.format.total ? this.format.total : this.format.n
const ratio = n/ this.format.total;
const percent = this.format.total ? 100 * ratio : 0;
const remaining = this.format.rate && this.format.total ? (this.format.total - n) / this.format.rate : 0; // Seconds

const numerator = this.isBytes ? humanReadableBytes(this.format.n) : this.format.n
const denominator = this.isBytes ? humanReadableBytes(this.format.total) : this.format.total
Expand Down
99 changes: 49 additions & 50 deletions src/electron/frontend/core/components/pages/Page.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { LitElement, html } from "lit";
import { runConversion } from "./guided-mode/options/utils.js";
import { run } from "./guided-mode/options/utils.js";
import { get, save } from "../../progress/index.js";

import { dismissNotification, notify } from "../../dependencies.js";
Expand Down Expand Up @@ -136,13 +136,10 @@ export class Page extends LitElement {
this.unsavedUpdates = true;

// Indicate conversion has run successfully
const { desyncedData } = this.info.globalState;
if (!desyncedData) this.info.globalState.desyncedData = {};

if (desyncedData) {
desyncedData[key] = false;
await this.save({}, false);
}
let { desyncedData } = this.info.globalState;
if (!desyncedData) desyncedData = this.info.globalState.desyncedData = {};
desyncedData[key] = false;
await this.save({}, false);
}

async runConversions(conversionOptions = {}, toRun, options = {}) {
Expand All @@ -157,18 +154,10 @@ export class Page extends LitElement {

const results = {};

const isMultiple = toRun.length > 1;

const swalOpts = await createProgressPopup({ title: `Running conversion`, ...options });
const { close: closeProgressPopup, elements } = swalOpts;

elements.container.insertAdjacentHTML(
"beforeend",
`<small><small><b>Note:</b> This may take a while to complete...</small></small><hr style="margin-bottom: 0;">`
);

let completed = 0;
elements.progress.format = { n: completed, total: toRun.length };
const { close: closeProgressPopup } = swalOpts;
const fileConfiguration = [];

for (let info of toRun) {
const { subject, session, globalState = this.info.globalState } = info;
Expand All @@ -187,44 +176,54 @@ export class Page extends LitElement {
source_data: merge(SourceData, sourceDataCopy),
};

const result = await runConversion(
{
output_folder: conversionOptions.stub_test ? undefined : conversion_output_folder,
project_name: name,
nwbfile_path: file,
overwrite: true, // We assume override is true because the native NWB file dialog will not allow the user to select an existing file (unless they approve the overwrite)
...sessionInfo, // source_data and metadata are passed in here
...conversionOptions, // Any additional conversion options override the defaults

interfaces: globalState.interfaces,
alignment,
},
swalOpts
).catch((error) => {
let message = error.message;

if (message.includes("The user aborted a request.")) {
this.notify("Conversion was cancelled.", "warning");
throw error;
}
const payload = {
output_folder: conversionOptions.stub_test ? undefined : conversion_output_folder,
project_name: name,
nwbfile_path: file,
overwrite: true, // We assume override is true because the native NWB file dialog will not allow the user to select an existing file (unless they approve the overwrite)
...sessionInfo, // source_data and metadata are passed in here
...conversionOptions, // Any additional conversion options override the defaults

this.notify(message, "error");
closeProgressPopup();
throw error;
});
interfaces: globalState.interfaces,
};

fileConfiguration.push(payload);
}

const conversionResults = await run(
`neuroconv/convert`,
{
files: fileConfiguration,
max_workers: 2, // TODO: Make this configurable and confirm default value
request_id: swalOpts.id,
},
{
title: "Running the conversion",
onError: () => "Conversion failed with current metadata. Please try again.",
...swalOpts,
}
).catch(async (error) => {
let message = error.message;

completed++;
if (isMultiple) {
const progressInfo = { n: completed, total: toRun.length };
elements.progress.format = progressInfo;
if (message.includes("The user aborted a request.")) {
this.notify("Conversion was cancelled.", "warning");
throw error;
}

this.notify(message, "error");
await closeProgressPopup();
throw error;
});

conversionResults.forEach((info) => {
const { file } = info;
const fileName = file.split("/").pop();
const [subject, session] = fileName.match(/sub-(.+)_ses-(.+)\.nwb/).slice(1);
const subRef = results[subject] ?? (results[subject] = {});
subRef[session] = result;
}
subRef[session] = info;
});

closeProgressPopup();
elements.container.style.textAlign = ""; // Clear style update
await closeProgressPopup();

return results;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import { electron } from "../../../../../utils/electron.js";
import { getSharedPath, removeFilePaths, truncateFilePaths } from "../../../preview/NWBFilePreview.js";
const { ipcRenderer } = electron;
import { until } from "lit/directives/until.js";
import { run } from "./utils";
import { run } from "./utils.js";
import { InspectorList, InspectorLegend } from "../../../preview/inspector/InspectorList.js";
import { getStubArray } from "./GuidedStubPreview.js";
import { InstanceManager } from "../../../InstanceManager.js";
import { getMessageType } from "../../../../validation/index.js";

import { Button } from "../../../Button.js";
import { Button } from "../../../Button";

import { download } from "../../inspect/utils.js";
import { createProgressPopup } from "../../../utils/progress.js";
Expand Down Expand Up @@ -184,16 +184,15 @@ export class GuidedInspectorPage extends Page {
"neuroconv/inspect_folder",
{ path, ...options, request_id: swalOpts.id },
swalOpts
).catch((error) => {
this.notify(error.message, "error");
closeProgressPopup();
return null;
});
)
.catch(async (error) => {
this.notify(error.message, "error");
return null;
})
.finally(() => closeProgressPopup());

if (!result) return "Failed to generate inspector report.";

closeProgressPopup();

this.report = globalState.preview.inspector = {
...result,
messages: truncateFilePaths(result.messages, path),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { onThrow } from "../../../errors";
import { Button } from "../../Button.js";

import { run } from "../guided-mode/options/utils.js";
import { JSONSchemaInput } from "../../JSONSchemaInput.js";
import { Modal } from "../../Modal";
import { getSharedPath, truncateFilePaths } from "../../preview/NWBFilePreview.js";
import { InspectorList, InspectorLegend } from "../../preview/inspector/InspectorList.js";
Expand All @@ -31,16 +30,15 @@ export class InspectPage extends Page {
});

const { close: closeProgressPopup } = swalOpts;

const result = await run("neuroconv/inspect", { request_id: swalOpts.id, paths, ...kwargs }, swalOpts).catch(
(error) => {
async (error) => {
this.notify(error.message, "error");
closeProgressPopup();
await closeProgressPopup();
throw error;
}
);

closeProgressPopup();
await closeProgressPopup();

if (typeof result === "string") return result;

Expand Down
2 changes: 1 addition & 1 deletion src/electron/frontend/core/components/pages/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const sanitize = (item, condition = isPrivate) => {
if (condition(k, value)) delete item[k];
else sanitize(value, condition);
}
}
} else if (Array.isArray(item)) item.forEach((value) => sanitize(value, condition));

return item;
};
Expand Down
13 changes: 9 additions & 4 deletions src/electron/frontend/core/components/utils/progress.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export const createProgressPopup = async (options, tqdmCallback) => {
textAlign: "left",
display: "flex",
flexDirection: "column",
overflow: "hidden",
width: "100%",
gap: "5px",
});
element.append(container);
Expand Down Expand Up @@ -74,13 +76,16 @@ export const createProgressPopup = async (options, tqdmCallback) => {

progressHandler.addEventListener("message", onProgressMessage);

const close = () => {
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

const close = async () => {
if (lastUpdate) {
// const timeSinceLastUpdate = now - lastUpdate;
const animationLeft = 1000; // ProgressBar.animationDuration - timeSinceLastUpdate; // Add 100ms to ensure the animation has time to complete
if (animationLeft) setTimeout(() => popup.close(), animationLeft);
else popup.close();
} else popup.close();
if (animationLeft) await sleep(animationLeft);
}

popup.close();

progressHandler.removeEventListener("message", onProgressMessage);
};
Expand Down
1 change: 1 addition & 0 deletions src/pyflask/manageNeuroconv/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from .info import CONVERSION_SAVE_FOLDER_PATH, STUB_SAVE_FOLDER_PATH
from .manage_neuroconv import (
autocomplete_format_string,
convert_all_to_nwb,
convert_to_nwb,
generate_dataset,
generate_test_data,
Expand Down
Loading
Loading