Skip to content

Bokeh and panel applications#101

Open
kujaku11 wants to merge 98 commits into
mainfrom
bokeh
Open

Bokeh and panel applications#101
kujaku11 wants to merge 98 commits into
mainfrom
bokeh

Conversation

@kujaku11

@kujaku11 kujaku11 commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Description

This PR adds panel applications that plot using a bokeh backend for rendering. The PR has a master panel application for loading in data, plotting, modeling. This will hopefully make mtpy a little easier to use.

Motivation and Context

A lot of the functionality of mtpy is through scripts, notebooks, and command line. The panel application adds a user interface that can run in a web browser.

How Has This Been Tested?

adding a test suite for the applications

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

kujaku11 and others added 30 commits April 29, 2026 23:07
Add a new mtpy.imaging.bokeh_plots package and a full Bokeh-based PlotMTResponse implementation (mtpy/imaging/bokeh_plots/plot_mt_response.py) that mirrors the existing matplotlib PlotMTResponse for use in Panel dashboards. The module includes interactive controls, Panel integration (make_panel), hover tools, tipper and phase tensor plotting, and handles optional Bokeh/Panel dependencies. Export PlotMTResponse from mtpy/imaging/bokeh_plots and re-export it in mtpy/imaging/__init__.py as PlotMTResponseBokeh. Remove the large legacy tests file tests/core/test_mt_data.py (deleted).
Introduce proper log-period x-axis ticks and formatting using FixedTicker and CustomJSTickFormatter and apply via a new _apply_log_period_ticks helper. Replace deprecated grid.grid_alpha with grid_line_alpha. Make x_range optional for resistivity figure and pass it via kwargs. Enhance hover tooltips for tip and polarization-ellipse plots and add missing data fields (phimin/phimax/azimuth/period) to the ColumnDataSource. Add a component "Preset" RadioButtonGroup with mappings (Off-diagonal, Full tensor, All), wire it to update component selection, and initialize components with the Off-diagonal preset. Minor efficiency tweak to use a precomputed count for valid points.
Replace tipper segment+marker rendering with Bokeh Arrow + NormalHead and add import/availability checks for Arrow and NormalHead. Add _tuple_to_hex to map matplotlib short color codes (e.g. 'k') and handle RGB tuples, convert tipper components to numpy arrays, filter out invalid/nonpositive periods, and include period in the tipper data source. Guard against empty tipper vectors and add legend entries via dummy lines. Add tests verifying arrow plotting and matplotlib short-color handling.
Add Bokeh Column/Row imports (with ImportError fallbacks) and replace gridplot-based assembly with Column/Row layouts to support 1- and 2-column panels and fixed widths. Parameterize tipper/PT figure widths and share x-range when both are present. Fix whisker head stroke color to match glyph color. Replace JS tick formatter to render full superscript exponents (including negative signs). Make phase-tensor ellipse sizing robust: avoid division-by-zero by scaling by the station max phimax, compute width/height from per-component phimax/phimin, and compute a rotated-geometry y-limit to avoid clipping. Remove y-axis labels from diagonal components and apply other layout/formatting adjustments for consistent sizing and interaction.
Introduce PlotMultipleResponses (Bokeh) and integrate multi-file plotting into the MTResponse panel app. Adds mtpy/imaging/bokeh_plots/plot_mt_responses.py implementing multi-station layouts (compare/single/all), legend handling, tipper and phase-tensor rendering, and Panel wrapping. Update __init__ to export the new class.

Update panel_mt_response_app.py to support selecting multiple files and new plot options (plot style, tipper selection, phase tensor toggle), consolidate file/option change handling, format station labels with survey id when available, and load MT objects via a helper. Single-file selection still uses PlotMTResponse; multi-file selection uses PlotMultipleResponses with appropriate options. Improve status messages and error reporting.
Introduce file-type filtering and validation for MTResponseApp: add supported file patterns/suffixes, a File Type select widget, and update the FileSelector to use the chosen pattern and a resolved data directory. Reject unsupported file suffixes before attempting to load with MT.read and clear stale selections/plots when the file filter changes. Also simplify pn.extension usage and add user-facing guidance in the UI. Add tests to verify rejection of unsupported files and that changing the file filter clears selections and plots.
Add interactive bad-data editing to the MT response panel: introduce a default data-directory helper, import numpy and scipy.interpolate, and add UI widgets (Apply Edits button, marked-points display) and state to track marked points and current MT data. Wire Bokeh Tap handlers to mark points on response/phase figures, provide _on_apply_edits_clicked to set marked Z/Tipper values to NaN and refresh the plot, and update helper methods to reflect edits. Also update tests to import required packages (scipy), add MT import, and add tests around period storage and interpolation error conditions. Overall this enables clicking points to mark them and applying edits to remove bad data in single-file mode.
Introduce Bokeh-based plotting for penetration-depth: add PlotPenetrationDepth1D and PlotPenetrationDepthMap implementations under mtpy/imaging/bokeh_plots, with optional Bokeh imports guarded and depth-unit handling (km/m). Update mtpy.imaging and mtpy.imaging.bokeh_plots __init__ exports. Implement map interpolation, color mapping, station markers, caching of computed depth arrays per plot period, and plotting configuration options. Add pytest tests for both 1D and map plotters to validate unit scaling, input validation, figure composition, sorting behavior, caching, and image renderer presence.
Introduce Bokeh-based plotting backends for phase-tensor maps and pseudosections and resistivity/phase pseudosections. Added PlotPhaseTensorMaps, PlotPhaseTensorPseudoSection, and PlotResPhasePseudoSection under mtpy/imaging/bokeh_plots, updated mtpy/imaging and mtpy/imaging/bokeh_plots __init__ exports, and included basic tests in tests/imaging to exercise the new Bokeh plotters. The new modules use optional Bokeh/Pandas/Scipy dependencies with graceful ImportError fallbacks and provide palette, colorbar, tipper/arrow, and interpolation handling consistent with existing mtpy plotting tools.
Introduce Bokeh-based plotting backends and tests for imaging. Adds three new Bokeh plotters: PlotPhaseTensor (plot_pt.py), PlotResPhaseMaps (plot_resphase_maps.py) and PlotStations (plot_stations.py), each implemented with optional Bokeh imports and graceful ImportError fallbacks. Export lists updated in mtpy/imaging/__init__.py and mtpy/imaging/bokeh_plots/__init__.py to expose new classes and top-level Bokeh aliases. Also include pytest-based tests for the new functionality (tests/imaging/*_bokeh.py) that exercise construction, plotting behaviour, interpolation caching, and top-level imports. These changes add map/ellipse/marker rendering, color mapping, hover tools, and support for MTData/MT objects while keeping Bokeh as an optional dependency.
Translate mtpy.imaging.plot_strike.PlotStrike to a Bokeh implementation
suitable for Panel dashboards.

- Add mtpy/imaging/bokeh_plots/plot_strike.py with PlotStrike class:
  - Rose diagrams rendered via Bokeh annular_wedge (no matplotlib)
  - Supports plot_type 1 (per-decade grid) and 2 (all-periods combined)
  - Full parity with matplotlib version: fold, plot_orthogonal,
    color gradients, ring_limits, plot_orientation, pt_error_floor
  - Identical data logic (make_strike_df, get_estimate, get_stats,
    get_plot_array, rotation_angle setter)
- Export PlotStrike from mtpy/imaging/bokeh_plots/__init__.py
- Export PlotStrikeBokeh alias from mtpy/imaging/__init__.py
- Add tests/imaging/test_plot_strike_bokeh.py with 22 pytest tests
  covering data processing, Bokeh plot structure, and import aliases

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- New panel_mt_data_app.py with MTDataApp class that allows users to
  select any mix of transfer function files (.edi, .xml, .avg, .zmm,
  .zss, .zrr) and/or an MTH5 (.h5) file via a unified FileSelector
- Loading logic: opens MTH5 first via MTCollection (if present), then
  merges additional TF files via MTData.add_stations()
- Station summary Tabulator widget shows survey/station/lat/lon/n_periods
- Save-to-MTH5 button writes the active MTData via MTCollection
- Reactive mt_data_loaded param flag for downstream panel watchers
- 20 unit tests covering all loading paths, mocked and real EDI

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- New panel_mt_data_app.py with MTDataApp class that allows users to
  select any mix of transfer function files (.edi, .xml, .avg, .zmm,
  .zss, .zrr) and/or an MTH5 (.h5) file via a unified FileSelector
- Loading logic: opens MTH5 first via MTCollection (if present), then
  merges additional TF files via MTData.add_stations()
- Station summary Tabulator widget shows survey/station/lat/lon/n_periods
- Save-to-MTH5 button writes the active MTData via MTCollection
- Reactive mt_data_loaded param flag for downstream panel watchers
- 20 unit tests covering all loading paths, mocked and real EDI

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kujaku11 and others added 30 commits May 25, 2026 16:45
Replace the single combined tipper arrow figure with two stacked
scatter+line plots (Tipper Real, Tipper Imaginary) sharing an x-axis,
consistent with how impedance components are displayed.

- tip_real_fig and tip_imag_fig share x_range for linked pan/zoom
- Per-station tipper drawn with station xy_color and xy_marker,
  matching impedance plot colours
- Zero-line, axis labels, log period ticks via shared helper
- Real subplot hides x-axis when imag is also shown
- Removed ctipr/ctipi colour ramps; tipper inherits station colour

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nslation

Adding functionality to the panel application.
Introduce a BokehPlotBase with a default make_panel() to wrap Bokeh layouts in Panel panes and centralise Panel import/errors. PlotPenetrationDepth1D now inherits from BokehPlotBase, stores renderers per component, and exposes an interactive make_panel() with mode toggles and depth-unit switching. Add a standalone PenetrationDepth1DApp (Panel application) for loading MT transfer function files and visualising 1-D Niblett–Bostick penetration depth. Integrate penetration depth viewing into MTDataApp by adding a pen_depth container, selection handling, and error/status reporting. Export BokehPlotBase from package __init__ and expand tests to cover the new base class, panel behaviours, and MTDataApp integration.
Introduce a Bokeh plotting backend and extend the Panel MTData app: add a new BokehPlotBase class (mtpy/imaging/bokeh_plots/bokeh_plot_base.py), export Bokeh-specific plot classes, and update imports. Add backend selection ("bokeh" | "matplotlib") to many MTData plotting APIs (plot_mt_response(s), plot_stations, plot_strike, plot_phase_tensor(_map/_pseudosection), plot_penetration_depth(_1d/_map), plot_resistivity_phase(_maps/_pseudosections), plot_tipper_map), routing to Bokeh classes when requested and validating backend values. Enhance the Panel app (panel_mt_data_app.py) with file-type handling (.dat/.data format selector), plot-type/backend widgets, improved station summary building, filesystem root helper, reset/append/edit controls, and other UI wiring. Add tests for Bokeh plotting and panel behavior, update .gitignore to ignore test HDF5, and add .github/copilot-instructions.md. Misc: rename bokeh base import and small formatting/whitespace fixes across files.
Expose a panel() alias on BokehPlotBase that forwards to make_panel so MTDataApp's plot dispatcher can call plot_obj.panel(). Call _update_penetration_depth when MTDataApp initializes selected station paths so the penetration-depth view is kept in sync. Simplify PlotPhaseTensor imports by removing the optional ImportError fallback (bokeh is now imported unconditionally), and update tests to cover the new alias, panel dispatch behavior, and table-selection -> _update_penetration_depth wiring.
Introduce BokehPlotBaseMaps (new file) that centralizes map interpolation and TF interpolation helpers (pre-interpolation cache, interp1d functions, and interpolated z/t/error retrieval). Export the new base in the package __init__.py and update map-based Bokeh plot classes (PlotPenetrationDepthMap, PlotResPhaseMaps, PlotPhaseTensorMaps) to inherit from BokehPlotBaseMaps, removing duplicated interpolation/cache code and unifying default settings (e.g. marker color hex).

Enhance PlotPhaseTensor (plot_pt.py): adopt param-driven kwargs, add palette options, improved ellipse sizing and spacing logic, add hover tooltips, and provide Panel integration (make_panel/panel) and controls. Minor UI/behavior tweaks (marker sizing, colors, line widths).

Add tests for BokehPlotBaseMaps and update existing panel tests to reflect API/behavior changes. Overall this refactors interpolation logic into a shared base and improves Bokeh phase-tensor plotting and interactivity.
Introduce a unified palette_options mapping (including rainbow and reversed variants) using Bokeh palettes and matplotlib colormaps, and expose it on BokehPlotBaseMaps. Harden interpolate_to_map by clamping nearest_neighbors to the number of available points. Simplify/normalize bokeh imports in PlotResPhaseMaps, use palette_options in _palette_from_name, and pass the full data array into _plot_component. Add a Panel-based interactive app (panel() and servable()) for resistivity/phase maps with controls for period, components, palettes, units and refresh behavior. Update tests to validate palette options, nearest_neighbors behavior, Panel integration, and new panel controls.
Derive palette options from self.palette_options and add two RangeSlider widgets (Resistivity Limits and Phase Limits) to the res/phase maps panel so users can set colorbar limits interactively. The refresh handler now reads these slider values and updates cmap_limits for all resistivity and phase components (res_xx,res_xy,res_yx,res_yy,res_det and phase_xx,phase_xy,phase_yx,phase_yy,phase_det). Tests updated to check for the new widgets and to verify their values propagate into plotter.cmap_limits.
Add tests to tests/imaging/test_plot_strike_bokeh.py: a test ensuring plot type 1 titles include decade superscripts, and a new TestPlotStrikeBokehPanel suite that requires panel and bokeh, provides a widget-finding helper, and verifies the plotter.panel() UI. The panel tests check returned layout type, presence of expected controls (selects, checkboxes, color pickers, check button groups), that the Refresh action updates plotter parameters/colors, and that servable() returns a viewable. This enhances UI coverage for the Strike Bokeh plotter.
Embed interactive Panel apps for Bokeh pseudosections and Phase Tensor pseudosections. Adds panel() and servable() methods to PlotResPhasePseudoSection and PlotPhaseTensorPseudoSection, with widget controls (palette, colorby, ranges, sizes, interpolation, station/axis stretches, etc.) and a Refresh action that rebuilds the plot. Also: use importlib to lazily require panel, introduce plain-text colorbar labels, replace period_label_dict axis formatting with simple 10^k labels, compute x padding from ellipse_size, and adjust default scaling values (ellipse_size, x_stretch, y_stretch). Minor import reordering and defensive error message when panel is missing. Tests updated/added to cover the new Panel integration, defaults, label formatting, and widget behavior.
Introduce BokehPlotBaseProfile (new file) to encapsulate profile/pseudosection helpers (profile line computation, offsets, rotation, iteration over MT objects) and wire it into the package __init__.py. Centralize palette construction and registry in bokeh_plot_base (matplotlib rainbow + Bokeh palettes) and expose palette options and palette_from_name helper; remove duplicated palette definitions from maps module. Update PlotPhaseTensorPseudoSection and PlotResPhasePseudoSection to inherit the new profile base, use the shared palette registry, adjust arrow sizing/appearance logic, add CSS color conversion and tipper label<->code mappings, and add new Panel widgets for arrow sizing and colors. Remove some unused/commented UI code in panel_mt_data_app. Add tests for BokehPlotBaseProfile and update existing phase-tensor tests to cover new arrow defaults and panel widgets.
Remove the Penetration Depth (1-D) panel and its divider from the MTDataApp layout (drop the _pen_depth_container/penetration_depth_section). Update pseudosection defaults: set resistivity colormap to 'turbo_r' (reversed turbo) and phase colormap to 'turbo' (previously 'viridis'). Also includes minor whitespace cleanup.
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.

1 participant