Ejemplo n.º 1
0
    class Meta:
        model = WorkstationConfig
        fields = (
            "title",
            "description",
            "image_context",
            "window_presets",
            "default_window_preset",
            "default_slab_thickness_mm",
            "default_slab_render_method",
            "default_orientation",
            "default_overlay_alpha",
            "overlay_luts",
            "default_overlay_lut",
            "default_image_interpolation",
            "default_overlay_interpolation",
            "overlay_segments",
            "key_bindings",
            "default_zoom_scale",
            "auto_jump_center_of_gravity",
            "link_images",
            "show_image_info_plugin",
            "show_display_plugin",
            "show_image_switcher_plugin",
            "show_algorithm_output_plugin",
            "show_overlay_plugin",
            "show_invert_tool",
            "show_flip_tool",
            "show_window_level_tool",
            "show_reset_tool",
            "show_overlay_selection_tool",
            "show_lut_selection_tool",
            "show_annotation_counter_tool",
            "enable_contrast_enhancement",
        )

        widgets = {
            "overlay_segments": JSONEditorWidget(
                schema=OVERLAY_SEGMENTS_SCHEMA
            ),
            "key_bindings": JSONEditorWidget(schema=KEY_BINDINGS_SCHEMA),
        }
        help_texts = {
            "overlay_segments": (
                model._meta.get_field("overlay_segments").help_text
                + ". If an categorical overlay is shown, it is possible to show toggles "
                "to change the visibility of the different overlay categories. To do "
                "so, configure the categories that should be displayed. Data from the"
                " algorithm's output.json can be added as an extra label to each "
                "toggle using jinja templating. "
                'For example: [{ "voxel_value": 0, "name": "Level 0", "visible": '
                'false, "metric_template": "{{metrics.volumes[0]}} mm³"},]'
            ),
            "window_presets": model._meta.get_field("window_presets").help_text
            + ". Select multiple presets by holding CTRL or dragging your mouse",
            "overlay_luts": model._meta.get_field("overlay_luts").help_text
            + ". Select multiple presets by holding CTRL or dragging your mouse",
            "key_bindings": model._meta.get_field("key_bindings").help_text
            + ". A copy and paste JSON can be obtained from the viewer",
        }
Ejemplo n.º 2
0
 class Meta(ReaderStudyCreateForm.Meta):
     fields = (
         "title",
         "logo",
         "social_image",
         "description",
         "publications",
         "modalities",
         "structures",
         "organizations",
         "workstation",
         "workstation_config",
         "help_text_markdown",
         "shuffle_hanging_list",
         "is_educational",
         "public",
         "allow_answer_modification",
         "allow_case_navigation",
         "allow_show_all_annotations",
         "hanging_list",
         "case_text",
     )
     widgets = {
         "hanging_list": JSONEditorWidget(schema=HANGING_LIST_SCHEMA),
         "case_text": JSONEditorWidget(schema=CASE_TEXT_SCHEMA),
         "help_text_markdown": MarkdownEditorWidget,
         "description": TextInput,
         "publications": Select2MultipleWidget,
         "modalities": Select2MultipleWidget,
         "structures": Select2MultipleWidget,
         "organizations": Select2MultipleWidget,
     }
     help_texts = {
         **READER_STUDY_HELP_TEXTS,
         "shuffle_hanging_list":
         ("If true, each reader will read the images in a unique "
          "order. The ordering for each user will be consistent over "
          "time. If false, the readers will all read the images in the "
          "order that you define in the hanging_list field."),
         "hanging_list":
         ("A list of hangings. "
          "The hanging defines which image (the hanging value) "
          "should be assigned to which image port or overlay. "
          "Options are: main, secondary, tertiary, quaternary, "
          "quinary, senary, septenary, octonary, nonary, denary. "
          "For instance: "
          '[{"main":"im1.mhd","main-overlay":"im1-overlay.mhd"}]'),
         "case_text":
         ("Free text that can be included for each case, where the key "
          "is the filename and the value is free text. You can use "
          "markdown formatting in the text. Not all images in the "
          "reader study are required. "
          'e.g., {"a73512ee-1.2.276.0.542432.3.1.3.3546325986342": "This is *image 1*"}'
          ),
     }
 class Meta:
     model = WorkstationConfig
     fields = (
         "title",
         "description",
         "image_context",
         "window_presets",
         "default_window_preset",
         "default_slab_thickness_mm",
         "default_slab_render_method",
         "default_orientation",
         "default_overlay_alpha",
         "overlay_luts",
         "default_overlay_lut",
         "default_overlay_interpolation",
         "overlay_segments",
         "key_bindings",
         "default_zoom_scale",
         "show_image_info_plugin",
         "show_display_plugin",
         "show_invert_tool",
         "show_flip_tool",
         "show_window_level_tool",
         "show_reset_tool",
         "enable_contrast_enhancement",
         "client_rendered_sidebar",
     )
     widgets = {
         "overlay_segments":
         JSONEditorWidget(schema=OVERLAY_SEGMENTS_SCHEMA),
         "key_bindings": JSONEditorWidget(schema=KEY_BINDINGS_SCHEMA),
     }
     help_texts = {
         "overlay_segments":
         ("If an categorical overlay is shown, it is possible to show toggles "
          "to change the visibility of the different overlay categories. To do "
          "so, configure the categories that should be displayed. Data from the"
          " algorithm's output.json can be added as an extra label to each "
          "toggle using jinja templating. "
          'For example: [{ "voxel_value": 0, "name": "Level 0", "visible": '
          'false, "metric_template": "{{metrics.volumes[0]}} mm³"},]'),
         "image_context":
         "This tells the viewer how to show the images "
         "defined in the hanging list",
         "window_presets":
         "These are the window LUT presets the viewer can choose between. "
         "By default, none are selected. "
         "Select multiple presets by holding CTRL or dragging your mouse",
     }
Ejemplo n.º 4
0
 class Meta(ReaderStudyCreateForm.Meta):
     fields = (
         "title",
         "logo",
         "description",
         "workstation",
         "shuffle_hanging_list",
         "hanging_list",
     )
     widgets = {
         "hanging_list": JSONEditorWidget(schema=HANGING_LIST_SCHEMA)
     }
     help_texts = {
         **READER_STUDY_HELP_TEXTS,
         "shuffle_hanging_list": (
             "If true, each reader will read the images in a unique "
             "order. The ordering for each user will be consistent over "
             "time. If false, the readers will all read the images in the "
             "order that you define in the hanging_list field."
         ),
         "hanging_list": (
             "A list of hangings. "
             "The hanging defines which image (the hanging value) "
             "should be assigned to which image port. "
             'e.g., [{"main":"im1.mhd","secondary":"im2.mhd"}]'
         ),
     }
Ejemplo n.º 5
0
 class Meta:
     model = HangingProtocol
     fields = ("title", "description", "json")
     widgets = {"json": JSONEditorWidget(schema=HANGING_PROTOCOL_SCHEMA)}
     help_texts = {
         "json":
         ("To display a single image in full size, define the "
          "protocol as follows: "
          '[{"viewport_name": "main", "x": 0,"y": 0,"w": 1,"h": 1,'
          '"fullsizable": true,"draggable": false,"selectable": true,'
          '"order": 0}]')
     }
Ejemplo n.º 6
0
 class Meta:
     widgets = {
         "view_content": JSONEditorWidget(schema=VIEW_CONTENT_SCHEMA),
     }
     help_texts = {
         "view_content":
         ("Indicate which Component Interfaces need to be displayed in "
          'which image port. E.g. {"main": ["interface1"]}. The first '
          "item in the list of interfaces will be the main image in "
          "the image port. The first overlay type interface thereafter "
          "will be rendered as an overlay. For now, any other items "
          "will be ignored by the viewer.")
     }
Ejemplo n.º 7
0
 class Meta:
     model = WorkstationConfig
     fields = (
         "title",
         "description",
         "window_presets",
         "default_window_preset",
         "default_slab_thickness_mm",
         "default_slab_render_method",
         "default_orientation",
         "default_overlay_alpha",
         "default_overlay_lut",
         "default_overlay_interpolation",
         "overlay_segments",
         "key_bindings",
         "default_zoom_scale",
         "show_image_info_plugin",
         "show_display_plugin",
         "show_invert_tool",
         "show_flip_tool",
         "show_window_level_tool",
         "show_reset_tool",
     )
     widgets = {
         "overlay_segments":
         JSONEditorWidget(schema=OVERLAY_SEGMENTS_SCHEMA),
         "key_bindings": JSONEditorWidget(schema=KEY_BINDINGS_SCHEMA),
     }
     help_texts = {
         "overlay_segments":
         ("If an categorical overlay is shown, it is possible to show toggles "
          "to change the visibility of the different overlay categories. To do "
          "so, configure the categories that should be displayed. Data from the"
          " algorithm's output.json can be added as an extra label to each "
          "toggle using jinja templating. "
          'For example: [{ "voxel_value": 0, "name": "Level 0", "visible": '
          'false, "metric_template": "{{metrics.volumes[0]}} mm³"},]'),
     }
Ejemplo n.º 8
0
 class Meta:
     model = Config
     fields = (
         *submission_options,
         *scoring_options,
         *leaderboard_options,
         *result_detail_options,
     )
     widgets = {
         "submission_page_html":
         SummernoteInplaceWidget(),
         "extra_results_columns":
         JSONEditorWidget(schema=EXTRA_RESULT_COLUMNS_SCHEMA),
     }
Ejemplo n.º 9
0
    def __init__(
        self,
        *,
        kind: InterfaceKind.InterfaceKindChoices,
        schema: Dict,
        initial=None,
        user=None,
        required=None,
        help_text="",
    ):
        field_type = InterfaceKind.get_default_field(kind=kind)
        kwargs = {"required": required}

        if initial is not None:
            kwargs["initial"] = initial

        if kind in InterfaceKind.interface_type_image():
            kwargs["widget"] = UserUploadMultipleWidget()
            kwargs["queryset"] = get_objects_for_user(
                user, "uploads.change_userupload", accept_global_perms=False
            ).filter(status=UserUpload.StatusChoices.COMPLETED)
            extra_help = IMAGE_UPLOAD_HELP_TEXT
        elif kind in InterfaceKind.interface_type_file():
            kwargs["widget"] = UserUploadSingleWidget(
                allowed_file_types=InterfaceKind.get_file_mimetypes(kind=kind)
            )
            kwargs["queryset"] = get_objects_for_user(
                user, "uploads.change_userupload", accept_global_perms=False
            ).filter(status=UserUpload.StatusChoices.COMPLETED)
            extra_help = f"{file_upload_text} .{kind.lower()}"
        elif kind in InterfaceKind.interface_type_json():
            default_schema = {
                **INTERFACE_VALUE_SCHEMA,
                "anyOf": [{"$ref": f"#/definitions/{kind}"}],
            }
            if field_type == forms.JSONField:
                kwargs["widget"] = JSONEditorWidget(schema=default_schema)
            kwargs["validators"] = [
                JSONValidator(schema=default_schema),
                JSONValidator(schema=schema),
            ]
            extra_help = ""
        else:
            raise RuntimeError(f"Unknown kind {kind}")

        self._field = field_type(
            help_text=_join_with_br(help_text, extra_help), **kwargs
        )
Ejemplo n.º 10
0
 class Meta:
     model = Phase
     fields = (
         *phase_options,
         *submission_options,
         *scoring_options,
         *leaderboard_options,
         *result_detail_options,
     )
     widgets = {
         "submission_page_html":
         SummernoteInplaceWidget(),
         "extra_results_columns":
         JSONEditorWidget(schema=EXTRA_RESULT_COLUMNS_SCHEMA),
         "submissions_open_at":
         forms.DateTimeInput(format=("%Y-%m-%dT%H:%M"),
                             attrs={"type": "datetime-local"}),
         "submissions_close_at":
         forms.DateTimeInput(format=("%Y-%m-%dT%H:%M"),
                             attrs={"type": "datetime-local"}),
     }
Ejemplo n.º 11
0
    def __init__(
        self,
        *,
        kind: InterfaceKind.InterfaceKindChoices,
        initial=None,
        user=None,
        help_text="",
    ):
        field_type = field_for_interface(kind)

        # bool can't be required
        kwargs = {
            "required": (kind != InterfaceKind.InterfaceKindChoices.BOOL),
        }

        extra_help = ""

        if initial is not None:
            kwargs["initial"] = initial
        if kind in InterfaceKind.interface_type_annotation():
            kwargs["widget"] = JSONEditorWidget(
                schema=ANSWER_TYPE_SCHEMA["definitions"][kind])
        if kind in InterfaceKind.interface_type_file():
            kwargs["widget"] = uploader.AjaxUploadWidget(multifile=False,
                                                         auto_commit=False)
            kwargs["validators"] = [
                ExtensionValidator(allowed_extensions=(f".{kind.lower()}", ))
            ]
            extra_help = f"{file_upload_text} .{kind.lower()}"
        if kind in InterfaceKind.interface_type_image():
            kwargs["widget"] = uploader.AjaxUploadWidget(multifile=True,
                                                         auto_commit=False)
            extra_help = IMAGE_UPLOAD_HELP_TEXT

        self._field = field_type(help_text=_join_with_br(
            help_text, extra_help),
                                 **kwargs)

        if user:
            self._field.widget.user = user
Ejemplo n.º 12
0
 class Meta(ReaderStudyCreateForm.Meta):
     fields = (
         "title",
         "logo",
         "social_image",
         "description",
         "publications",
         "modalities",
         "structures",
         "organizations",
         "workstation",
         "workstation_config",
         "hanging_protocol",
         "view_content",
         "help_text_markdown",
         "shuffle_hanging_list",
         "is_educational",
         "public",
         "access_request_handling",
         "allow_answer_modification",
         "allow_case_navigation",
         "allow_show_all_annotations",
         "roll_over_answers_for_n_cases",
         "hanging_list",
         "case_text",
     )
     widgets = {
         "hanging_list": JSONEditorWidget(schema=HANGING_LIST_SCHEMA),
         "case_text": JSONEditorWidget(schema=CASE_TEXT_SCHEMA),
         "help_text_markdown": MarkdownEditorWidget,
         "description": TextInput,
         "publications": Select2MultipleWidget,
         "modalities": Select2MultipleWidget,
         "structures": Select2MultipleWidget,
         "organizations": Select2MultipleWidget,
     }
     widgets.update(ViewContentMixin.Meta.widgets)
     help_texts = {
         **READER_STUDY_HELP_TEXTS,
         "shuffle_hanging_list":
         ("If true, each reader will read the cases in a unique "
          "order. The ordering for each user will be consistent over "
          "time. If false, the readers will all read the cases in the "
          "order that you define."),
         "hanging_list":
         ("A list of hangings. "
          "The hanging defines which image (the hanging value) "
          "should be assigned to which image port or overlay. "
          "Options are: main, secondary, tertiary, quaternary, "
          "quinary, senary, septenary, octonary, nonary, denary. "
          "For instance: "
          '[{"main":"im1.mhd","main-overlay":"im1-overlay.mhd"}]'),
         "case_text":
         ("Free text that can be included for each case, where the key "
          "is the filename and the value is free text. You can use "
          "markdown formatting in the text. Not all images in the "
          "reader study are required. "
          'e.g., {"a73512ee-1.2.276.0.542432.3.1.3.3546325986342": "This is *image 1*"}'
          ),
         "hanging_protocol":
         format_lazy(
             ("The hanging protocol to use for this reader study. "
              "If a suitable protocol does not exist you can "
              '<a href="{}">create a new one</a>. For a list of existing '
              'hanging protocols, go <a href="{}">here</a>.'),
             reverse_lazy("hanging-protocols:create"),
             reverse_lazy("hanging-protocols:list"),
         ),
     }
     help_texts.update(ViewContentMixin.Meta.help_texts)