Add standardized client preprocessing capabilities#52
Add standardized client preprocessing capabilities#52bourdaisj wants to merge 6 commits intoKitware:masterfrom
Conversation
b6f44be to
5d422ba
Compare
520fe14 to
d3293d6
Compare
169750e to
71e5673
Compare
603ff7c to
910dd80
Compare
|
I think the issue is because the vue2 client is not built. |
|
You may need to pre-create the directory. |
|
I'm confused... the folder is here, it is in the wheel, it is packaged, it has a init.py in it. so why would it missing? Thx for the tip anyway, i'll continue investigating |
|
well turns out the init.py was gitignored, feeling dumb right now. CI is now green! I'll finalize this and mark as ready |
This new PreProcessor widget aims to allow library consumers to register JS module files with minimal boilerplate, and later call functions defined in those registered modules at runtime inside the trame client
previously, only ES module were supported. Library consumer can now pass .umd.js files
5fab55d to
9fd5195
Compare
9fd5195 to
31cbe9d
Compare
|
I'll try to do a final review this weekend so we can merge it sometime next week. |
|
I still need to iron out the public API, write some docstring for the readthedocs, and figure out how I can test this effectively, but that should not take too long. i'll tag you once done. |
661fac1 to
98b18db
Compare
|
@jourdain I pushed something that aim to keep the API simple and usable while decoupling from the widget module. wdyt? |
| from trame.ui.vuetify3 import SinglePageLayout | ||
|
|
||
| from trame.widgets import client, vuetify3, html | ||
| from trame_client.preprocessor import register_preprocessing_script |
There was a problem hiding this comment.
Any way for not importing things from trame_client.*? Can we just do something like
from trame.widgets import client, vuetify3, html
client.register_external_script(
name="validate_dicom_patient_name",
script_file_path=DICOM_UTILS_SCRIPT,
function_names=["validateDicomFilePatientName"],
)There was a problem hiding this comment.
It could be nice if we could use that same method to point to standalone JS file too that do not need method/function to be called.
There was a problem hiding this comment.
I did not want to pollute the widget file with too many dependencies, but yes - I think a good workaround is too keep all public API in trame.widgets.client. make sense to me
| vuetify3.VRow(), | ||
| vuetify3.VCol(cols=3), | ||
| # 3. Instantiate the PreProcessor widget | ||
| client.PreProcessor( |
There was a problem hiding this comment.
What about ?
client.Handler(
mode="pre-processing", # <= I don't know that we need that, but I'm thinking out loud for some genericity
function="validate_dicom_patient_name",
input=...,
completed=....
)There was a problem hiding this comment.
Handler might be good - yet, I'm not keen of one-word components/widgets.
what about: ScriptHandler, ScriptDispatcher.
what would be some other values of mode param?
There was a problem hiding this comment.
I don't actually know if we have different behavior/value for that property. So if you don't think of any, no need to add it.
I still prefer Handler than ScriptHandler. The reason is that it is a client Handler, but I don't see the point of saying client.ClientHandler
| self.preprocessing_pipeline_completed, | ||
| "[$event.type, $event.outputs]", | ||
| ), | ||
| ) as patient_name_preprocessor, |
| # Mark your state as client_only! | ||
| self.state.client_only("dicom_file_set") | ||
|
|
||
| register_preprocessing_script( |
There was a problem hiding this comment.
client.register_external_script(...
| persistent_hint=True, | ||
| ) | ||
|
|
||
| with client.PreProcessor( |
| failure=(self.handle_nifti_convertion_error, "[$event]"), | ||
| # error event for any exception raised during logic execution | ||
| error=(self.handle_nifti_convertion_error, "[$event]"), | ||
| ) as preprocessing: |
| # Mark your state as client_only! | ||
| self.state.client_only("dicom_file_set") | ||
|
|
||
| self.dicom_utils_preprocessor = register_preprocessing_script( |
There was a problem hiding this comment.
client.register_external_script(...
| vuetify3.VContainer(fluid=True), | ||
| vuetify3.VRow(), | ||
| vuetify3.VCol(cols=3), | ||
| client.PreProcessor( |
| "[$event.type, $event.outputs]", | ||
| ), | ||
| ), | ||
| client.PreProcessor( |
| def __init__(self, server=None): | ||
| super().__init__(server) | ||
|
|
||
| self.read_dicom_tags_preprocessor_logic = register_preprocessing_script( |
There was a problem hiding this comment.
client.register_external_script
| self.state.decimation_factor = 5 | ||
| self.state.hole_size = 1000.0 | ||
|
|
||
| register_preprocessing_script( |
There was a problem hiding this comment.
client.register_external_script
| self.ui.title.set_text("Client Preprocessing UMD Modules") | ||
|
|
||
| with self.ui.toolbar: | ||
| with client.PreProcessor( |
| @@ -0,0 +1,3 @@ | |||
| * | |||
| !__init__.py | |||
There was a problem hiding this comment.
Do you need the init.py in that directory?
There was a problem hiding this comment.
Yes, it is needed so that it ends up being packaged into the wheel
There was a problem hiding this comment.
No, you can be explicit that the directory contains non py file. That is inside the pyproject.toml that you have to specify that.
|
|
||
| def get_user_preprocessor_serve_url_prefix() -> Path: | ||
| return Path("__trame_client_preprocessors") | ||
|
|
There was a problem hiding this comment.
All those Path() should be const rather than methods.
There was a problem hiding this comment.
I get your comment, but I don't like things that can get modified from the outside - or is there some kind of "real" const in python?
There was a problem hiding this comment.
No but if you don't expose them, they are only available in that module and therefore not editable.
|
|
||
| server.enable_module( | ||
| { | ||
| "serve": {root_path.as_posix(): str(serve_path)}, |
There was a problem hiding this comment.
Include version to prevent conflicting client version capability?
There was a problem hiding this comment.
Let side could be { "serve: f"/__trame_client_handlers_{__version__}" : ... }
There was a problem hiding this comment.
from trame_client import __version__
There was a problem hiding this comment.
definitely. Looking at this, I'm also thinking the user script should be versioned/namespaced in some way so that they are cache friendly. probably a hash of the file would do the trick
There was a problem hiding this comment.
We have some logic doing that kind of stuff here: https://github.com/Kitware/trame-client/blob/master/trame_client/utils/web_module.py
| "get_user_preprocessor_scripts_path", | ||
| "get_user_preprocessor_es_scripts_path", | ||
| "get_user_preprocessor_umd_scripts_path", | ||
| "get_user_preprocessor_serve_url_prefix", |
There was a problem hiding this comment.
Do we need those to be exposed?
I think the server needs to see setup
| "DeepReactive", | ||
| "LifeCycleMonitor", | ||
| "SizeObserver", | ||
| "PreProcessor", |
| @@ -0,0 +1,127 @@ | |||
| from pathlib import Path | |||
There was a problem hiding this comment.
name the file external_script_handler.py ?
There was a problem hiding this comment.
user_provided_script_handler? or consumer_provided_script_handler?
There was a problem hiding this comment.
I technically don't care for that file name (as it is not public), so you can be as explicit as you want. I just don't like preprocessor.py
98b18db to
0ed2f55
Compare
|
I like all your changes, I think we are getting really close. I guess I just want to get rid of the "preprocess*" properties and make them more generic. |
This PR adds a widget to the client that aims to allow library consumers to register and run JS modules files with minimal boilerplate on the client side.
This PR is currently a draft.
Things that I am planning to do before marking as ready:
EDIT:
EDIT: