Loading lib/galaxy/datatypes/images.py +6 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import mrcfile import numpy as np import png import tifffile from typing_extensions import Literal try: import PIL Loading Loading @@ -65,6 +66,7 @@ class Image(data.Data): edam_data = "data_2968" edam_format = "format_3547" file_ext = "" display_behavior: Literal["inline", "download"] = "inline" # Most image formats can be displayed inline in browsers MetadataElement( name="axes", Loading Loading @@ -419,18 +421,22 @@ class OMEZarr(data.ZarrDirectory): class Hamamatsu(Image): file_ext = "vms" display_behavior = "download" # Proprietary microscopy format, not browser-displayable class Mirax(Image): file_ext = "mrxs" display_behavior = "download" # Proprietary microscopy format, not browser-displayable class Sakura(Image): file_ext = "svslide" display_behavior = "download" # Proprietary microscopy format, not browser-displayable class Nrrd(Image): file_ext = "nrrd" display_behavior = "download" # Medical imaging format, not browser-displayable class Bmp(Image): Loading lib/galaxy/datatypes/registry.py +0 −16 Original line number Diff line number Diff line Loading @@ -516,22 +516,6 @@ class Registry: def get_display_sites(self, site_type): return self.display_sites.get(site_type, []) def get_preferred_visualization(self, datatype_extension): """ Get the preferred visualization mapping for a specific datatype extension. Returns a dictionary with 'visualization' and 'default_params' keys, or None if no mapping exists. Preferred visualizations are defined inline within each datatype definition in the datatypes_conf.xml configuration file. These mappings determine which visualization plugin should be used by default when viewing datasets of a specific type. Example configuration: <datatype extension="bam" type="galaxy.datatypes.binary:Bam" mimetype="application/octet-stream" display_in_upload="true"> <visualization plugin="igv" /> </datatype> """ return self.visualization_mappings.get(datatype_extension) def get_all_visualization_mappings(self): """ Get all datatype to visualization mappings. Loading lib/galaxy/managers/datatypes.py +46 −0 Original line number Diff line number Diff line Loading @@ -163,6 +163,51 @@ def view_visualization_mappings( return parse_obj_as(DatatypeVisualizationMappingsList, mappings) def get_preferred_visualization(datatypes_registry: Registry, datatype_extension: str) -> Optional[Dict[str, str]]: """ Get the preferred visualization mapping for a specific datatype extension. Returns a dictionary with 'visualization' and 'default_params' keys, or None if no mapping exists. Preferred visualizations are defined inline within each datatype definition in the datatypes_conf.xml configuration file. These mappings determine which visualization plugin should be used by default when viewing datasets of a specific type. If no direct mapping exists for the extension, this method will walk up the inheritance chain to find a preferred visualization from a parent datatype class. Example configuration: <datatype extension="bam" type="galaxy.datatypes.binary:Bam" mimetype="application/octet-stream" display_in_upload="true"> <visualization plugin="igv" /> </datatype> """ direct_mapping = datatypes_registry.visualization_mappings.get(datatype_extension) if direct_mapping: return direct_mapping current_datatype = datatypes_registry.get_datatype_by_extension(datatype_extension) if not current_datatype: return None # Use the same mapping approach as the datatypes API for consistency mapping_data = view_mapping(datatypes_registry) current_class_name = mapping_data.ext_to_class_name.get(datatype_extension) if not current_class_name: return None current_class_mappings = mapping_data.class_to_classes.get(current_class_name, {}) for ext, visualization_mapping in datatypes_registry.visualization_mappings.items(): if ext == datatype_extension: continue parent_class_name = mapping_data.ext_to_class_name.get(ext) if parent_class_name and parent_class_name in current_class_mappings: return visualization_mapping return None __all__ = ( "DatatypeConverterList", "DatatypeDetails", Loading @@ -179,4 +224,5 @@ __all__ = ( "view_edam_formats", "view_edam_data", "view_visualization_mappings", "get_preferred_visualization", ) lib/galaxy/webapps/galaxy/api/datatypes.py +23 −5 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ from fastapi import ( ) from galaxy.datatypes.registry import Registry from galaxy.exceptions import ObjectNotFound from galaxy.managers.datatypes import ( DatatypeConverterList, DatatypeDetails, Loading @@ -25,6 +26,7 @@ from galaxy.managers.datatypes import ( DatatypesEDAMDetailsDict, DatatypesMap, DatatypeVisualizationMappingsList, get_preferred_visualization, view_converters, view_edam_data, view_edam_formats, Loading @@ -33,8 +35,10 @@ from galaxy.managers.datatypes import ( view_sniffers, view_visualization_mappings, ) from galaxy.structured_app import StructuredApp from . import ( depends, DependsOnApp, Router, ) Loading Loading @@ -64,6 +68,7 @@ IdentifierOnly: Optional[bool] = Query( @router.cbv class FastAPIDatatypes: datatypes_registry: Registry = depends(Registry) app: StructuredApp = DependsOnApp @router.get( "/api/datatypes", Loading Loading @@ -253,11 +258,24 @@ class FastAPIDatatypes: if converters: result["converters"] = list(converters.keys()) # Add preferred visualization if any preferred_viz = self.datatypes_registry.get_preferred_visualization(datatype) # Add preferred visualization if any and if the plugin is available preferred_viz = get_preferred_visualization(self.datatypes_registry, datatype) if preferred_viz: plugin_name = preferred_viz["visualization"] # Check if the visualization plugin is actually available try: if self.app.visualizations_registry: self.app.visualizations_registry.get_plugin(plugin_name) result["preferred_visualization"] = { "visualization": preferred_viz["visualization"], "visualization": plugin_name, } else: log.warning( f"Visualizations registry not available, skipping preferred visualization for '{datatype}'" ) except ObjectNotFound: # Plugin not available, don't include preferred_visualization log.warning(f"Preferred visualization '{plugin_name}' for datatype '{datatype}' is not available") return result Loading
lib/galaxy/datatypes/images.py +6 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import mrcfile import numpy as np import png import tifffile from typing_extensions import Literal try: import PIL Loading Loading @@ -65,6 +66,7 @@ class Image(data.Data): edam_data = "data_2968" edam_format = "format_3547" file_ext = "" display_behavior: Literal["inline", "download"] = "inline" # Most image formats can be displayed inline in browsers MetadataElement( name="axes", Loading Loading @@ -419,18 +421,22 @@ class OMEZarr(data.ZarrDirectory): class Hamamatsu(Image): file_ext = "vms" display_behavior = "download" # Proprietary microscopy format, not browser-displayable class Mirax(Image): file_ext = "mrxs" display_behavior = "download" # Proprietary microscopy format, not browser-displayable class Sakura(Image): file_ext = "svslide" display_behavior = "download" # Proprietary microscopy format, not browser-displayable class Nrrd(Image): file_ext = "nrrd" display_behavior = "download" # Medical imaging format, not browser-displayable class Bmp(Image): Loading
lib/galaxy/datatypes/registry.py +0 −16 Original line number Diff line number Diff line Loading @@ -516,22 +516,6 @@ class Registry: def get_display_sites(self, site_type): return self.display_sites.get(site_type, []) def get_preferred_visualization(self, datatype_extension): """ Get the preferred visualization mapping for a specific datatype extension. Returns a dictionary with 'visualization' and 'default_params' keys, or None if no mapping exists. Preferred visualizations are defined inline within each datatype definition in the datatypes_conf.xml configuration file. These mappings determine which visualization plugin should be used by default when viewing datasets of a specific type. Example configuration: <datatype extension="bam" type="galaxy.datatypes.binary:Bam" mimetype="application/octet-stream" display_in_upload="true"> <visualization plugin="igv" /> </datatype> """ return self.visualization_mappings.get(datatype_extension) def get_all_visualization_mappings(self): """ Get all datatype to visualization mappings. Loading
lib/galaxy/managers/datatypes.py +46 −0 Original line number Diff line number Diff line Loading @@ -163,6 +163,51 @@ def view_visualization_mappings( return parse_obj_as(DatatypeVisualizationMappingsList, mappings) def get_preferred_visualization(datatypes_registry: Registry, datatype_extension: str) -> Optional[Dict[str, str]]: """ Get the preferred visualization mapping for a specific datatype extension. Returns a dictionary with 'visualization' and 'default_params' keys, or None if no mapping exists. Preferred visualizations are defined inline within each datatype definition in the datatypes_conf.xml configuration file. These mappings determine which visualization plugin should be used by default when viewing datasets of a specific type. If no direct mapping exists for the extension, this method will walk up the inheritance chain to find a preferred visualization from a parent datatype class. Example configuration: <datatype extension="bam" type="galaxy.datatypes.binary:Bam" mimetype="application/octet-stream" display_in_upload="true"> <visualization plugin="igv" /> </datatype> """ direct_mapping = datatypes_registry.visualization_mappings.get(datatype_extension) if direct_mapping: return direct_mapping current_datatype = datatypes_registry.get_datatype_by_extension(datatype_extension) if not current_datatype: return None # Use the same mapping approach as the datatypes API for consistency mapping_data = view_mapping(datatypes_registry) current_class_name = mapping_data.ext_to_class_name.get(datatype_extension) if not current_class_name: return None current_class_mappings = mapping_data.class_to_classes.get(current_class_name, {}) for ext, visualization_mapping in datatypes_registry.visualization_mappings.items(): if ext == datatype_extension: continue parent_class_name = mapping_data.ext_to_class_name.get(ext) if parent_class_name and parent_class_name in current_class_mappings: return visualization_mapping return None __all__ = ( "DatatypeConverterList", "DatatypeDetails", Loading @@ -179,4 +224,5 @@ __all__ = ( "view_edam_formats", "view_edam_data", "view_visualization_mappings", "get_preferred_visualization", )
lib/galaxy/webapps/galaxy/api/datatypes.py +23 −5 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ from fastapi import ( ) from galaxy.datatypes.registry import Registry from galaxy.exceptions import ObjectNotFound from galaxy.managers.datatypes import ( DatatypeConverterList, DatatypeDetails, Loading @@ -25,6 +26,7 @@ from galaxy.managers.datatypes import ( DatatypesEDAMDetailsDict, DatatypesMap, DatatypeVisualizationMappingsList, get_preferred_visualization, view_converters, view_edam_data, view_edam_formats, Loading @@ -33,8 +35,10 @@ from galaxy.managers.datatypes import ( view_sniffers, view_visualization_mappings, ) from galaxy.structured_app import StructuredApp from . import ( depends, DependsOnApp, Router, ) Loading Loading @@ -64,6 +68,7 @@ IdentifierOnly: Optional[bool] = Query( @router.cbv class FastAPIDatatypes: datatypes_registry: Registry = depends(Registry) app: StructuredApp = DependsOnApp @router.get( "/api/datatypes", Loading Loading @@ -253,11 +258,24 @@ class FastAPIDatatypes: if converters: result["converters"] = list(converters.keys()) # Add preferred visualization if any preferred_viz = self.datatypes_registry.get_preferred_visualization(datatype) # Add preferred visualization if any and if the plugin is available preferred_viz = get_preferred_visualization(self.datatypes_registry, datatype) if preferred_viz: plugin_name = preferred_viz["visualization"] # Check if the visualization plugin is actually available try: if self.app.visualizations_registry: self.app.visualizations_registry.get_plugin(plugin_name) result["preferred_visualization"] = { "visualization": preferred_viz["visualization"], "visualization": plugin_name, } else: log.warning( f"Visualizations registry not available, skipping preferred visualization for '{datatype}'" ) except ObjectNotFound: # Plugin not available, don't include preferred_visualization log.warning(f"Preferred visualization '{plugin_name}' for datatype '{datatype}' is not available") return result