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

Web UI #7

Merged
merged 19 commits into from
Aug 26, 2024
Merged

Web UI #7

merged 19 commits into from
Aug 26, 2024

Conversation

nilsmechtel
Copy link
Member

Register data providing service in pyodide environment to:

  • serve image files from the mounted folder (/mnt/)
  • save annotation masks to the annotations folder (/mnt/annotations/)

Challenge:

  • Run loop.run_forever() but return the annotator_url from pyodide to the main thread

Notes:

  • Multiple options are listed in docs/services.py
  • The value of annotationURL is currently being displayed in the Sidebar for testing purposes
  • With the initial commit the annotator_url can be found in the logs, but the link doesn't work.

General question, does an imjoy plugin work with hypha-rpc?
Plugin: https://github.com/bioimage-io/bioimageio-colab/blob/web-ui/plugins/bioimageio-colab-annotator.imjoy.html
Generation of annotator URL:

annotation_sid = svc["id"]
config_str = f'{{"server_url": "{SERVER_URL}", "annotation_service_id": "{annotation_sid}", "token": "{token}"}}'
encoded_config = urllib.parse.quote(
config_str, safe="/", encoding=None, errors=None
)
annotator_url = f"https://imjoy.io/lite?plugin={PLUGIN_URL}&config={encoded_config}"

@nilsmechtel
Copy link
Member Author

@oeway do you have an idea how to communicate the annotation URL to the main thread?

@oeway
Copy link
Collaborator

oeway commented Aug 21, 2024

Hi @nilsmechtel Found a solution for you, you can basically break the code into 3 blocks and run it in 3 times (calling runCode): 1) run the code to get the register_service function 2) register the service (here you can then get the url from its return) 3) you can do run_forever;

I will make a commit soon.

Copy link
Collaborator

@oeway oeway left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @nilsmechtel I made some comments to help you understand my changes.

docs/index.html Outdated
});
}, []);
<script type="module">
import { get, set } from 'https://cdn.jsdelivr.net/npm/idb-keyval@6/+esm';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nilsmechtel This is for saving file handle into indexeddb, so we don't need to select the folder every time when the page reload

const [activeTab, setActiveTab] = useState("Local Deployment");

useEffect(() => {
workerPromise = new Promise((resolve, reject) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used a promise here, so we can defer the loading process, only wait for it when the user click deploy annotation. You can see how Promise works.

docs/index.html Outdated
"server_url": serverURL,
"login_callback": loginCallback,
});
localStorage.setItem('token', token);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here the token is saved so we can pass it to the pyodide worker later.

docs/index.html Outdated
const code = await fetch(`./${REGISTER_SERVICE_FILE}`).then(response => response.text());
try {
setIsRunning(true);
await workerPromise;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is when we actually wait for the worker ready (it start loading when the page loaded, and keep loading in the background).

docs/index.html Outdated
}
const outputs = await runCode(`await register_service("${server_url}", "${token}")`);
// find an output which contains type=service
const serviceOutput = outputs.find(output => output.type === 'service');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The worker has a mechanism to detect service, so we use the type 'service' to capture directly the registered service instead of parsing the stdout (this is a prefered approach), once you get the service url, you can then create an annotation url in js.

docs/services.py Outdated
@@ -89,17 +89,28 @@ async def register_service(callback):
}
)

# Create the annotator URL
annotation_sid = svc["id"]
config_str = f'{{"server_url": "{SERVER_URL}", "annotation_service_id": "{annotation_sid}", "token": "{token}"}}'
encoded_config = urllib.parse.quote(
config_str, safe="/", encoding=None, errors=None
)
annotator_url = f"https://imjoy.io/lite?plugin={PLUGIN_URL}&config={encoded_config}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the annotation plugin need to updated to use hypha rpc instead of imjoy rpc. Also I would create this annotation url in js instead of python.

docs/index.html Outdated Show resolved Hide resolved
@oeway oeway temporarily deployed to github-pages August 26, 2024 03:46 — with GitHub Pages Inactive
@oeway oeway temporarily deployed to github-pages August 26, 2024 04:51 — with GitHub Pages Inactive
@oeway oeway temporarily deployed to github-pages August 26, 2024 05:11 — with GitHub Pages Inactive
@oeway oeway merged commit 2eeaa76 into main Aug 26, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants