Interactive Controls
- apply_command
- key_press
- mouse_event
- flush_log
- set_active_region_index
- clear_buffer
- set_clear_buffer
- redraw
- set_redraw
- Interactive Application Development
apply_command
apply_command(command: str) -> 'Gw
Apply a GW command string.
Parameters:
command
(str): GW command to execute (e.g., “filter”, “count”, etc.)
key_press
key_press(key: int, scancode: int, action: int, mods: int) -> None
Process a key press event.
Parameters:
key
(int): Key codescancode
(int): Scan codeaction
(int): Key action codemods
(int): Modifier keys
mouse_event
mouse_event(x_pos: float, y_pos: float, button: int, action: int) -> None
Process a mouse event.
Parameters:
x_pos
(float): Mouse x-positiony_pos
(float): Mouse y-positionbutton
(int): Mouse button code (can be “left”, “right”)action
(int): Mouse action code
flush_log
flush_log() -> str
Returns and clears the GW log. This is useful for retrieving messages generated by GW during operation.
Returns:
str
: GW log as a python string
Example:
# Get any messages from GW
log_messages = gw.flush_log()
print(log_messages)
set_active_region_index
set_active_region_index(index: int) -> 'Gw'
Set the currently active region for visualisation. Subsequent mouse/key interactions will affect this region index.
Parameters:
index
(int): Index of the region to activate
Returns:
Gw
: Self for method chaining
clear_buffer
clear_buffer -> bool
Property that indicates whether the read buffer should be cleared on the next draw.
Returns:
bool
: Read buffer needs clearing
Example:
# Check if buffer needs clearing
if gw.clear_buffer:
print("Buffer will be cleared on next draw")
set_clear_buffer
set_clear_buffer(state: bool) -> None
Set the clear_buffer status.
Parameters:
state
(bool): If True, buffer will be cleared on next draw
Example:
# Force buffer clearing on next draw
gw.set_clear_buffer(True)
redraw
redraw -> bool
Property that indicates whether a re-draw needs to occur. Check this after some event e.g. command or mouse button.
Returns:
bool
: Image needs to be re-drawn
Example:
# Check if a redraw is needed
if gw.redraw:
gw.draw()
set_redraw
set_redraw(state: bool) -> None
Set the redraw status. For dynamic applications, set this to False after a drawing call to avoid unnecessary redraws.
Parameters:
state
(bool): If True, a redraw will be triggered
Example:
# Set redraw status
gw.set_redraw(False) # Prevent automatic redraw
Interactive Application Development
Creating interactive applications with gwplot involves managing drawing states, handling user interactions, and efficiently updating the visualization. Here’s a practical approach based on real-world usage:
from gwplot import Gw, GLFW
from flask import Flask, request, jsonify, send_file
import io
# Initialize Gw with a reference genome
gw = Gw("hg38", canvas_width=1200, canvas_height=800)
gw.add_bam("sample.bam")
gw.add_region("chr1", 1000000, 1100000)
# Handle mouse events
def handle_mouse_interaction(x_pos, y_pos, button, action):
# Convert button names to constants if needed
button_code = GLFW.MOUSE_BUTTON_LEFT if button == "left" else GLFW.MOUSE_BUTTON_RIGHT
action_code = GLFW.PRESS if action == "press" else GLFW.RELEASE
# Process the mouse event
gw.mouse_event(x_pos, y_pos, button_code, action_code)
# Check if we need to redraw
if gw.redraw:
gw.draw()
return True
return False
# Handle keyboard interactions
def handle_key_press(key):
# Map keys to GLFW constants
key_mapping = {
'ArrowRight': GLFW.KEY_RIGHT,
'ArrowLeft': GLFW.KEY_LEFT,
'ArrowUp': GLFW.KEY_UP,
'ArrowDown': GLFW.KEY_DOWN,
}
if key in key_mapping:
key_code = key_mapping[key]
scancode = GLFW.get_key_scancode(key_code)
gw.key_press(key_code, scancode, GLFW.PRESS, 0)
# Check if we need to redraw
if gw.redraw:
gw.draw()
return True
return False
# Handle command input
def handle_command(cmd_text):
gw.apply_command(cmd_text)
# Get any log output from the command
log_output = gw.flush_log()
# Check if we need to redraw or clear buffer
needs_redraw = gw.redraw
needs_clear = gw.clear_buffer
if needs_redraw:
gw.draw(clear_buffer=needs_clear)
return True, log_output
return False, log_output
# Get image data for display
def get_image_data():
# Encode as PNG (higher quality but larger size)
img_data = gw.encode_as_png()
# Alternative: faster but lower quality
# img_data = gw.encode_as_jpeg(quality=80)
return img_data
Web Application Integration
The above functions can be integrated into a web framework like Flask to create interactive browser-based applications:
app = Flask(__name__)
@app.route('/display_image')
def display_image():
gw.draw() # Ensure the latest state is drawn
img_data = gw.encode_as_png()
img_io = io.BytesIO(img_data)
img_io.seek(0)
return send_file(img_io, mimetype='image/png')
@app.route('/mouse-event', methods=['POST'])
def mouse_event():
data = request.get_json()
x_pos = data.get('x')
y_pos = data.get('y')
button = data.get('button') # "left" or "right"
action = data.get('action') # "press" or "release"
needs_redraw = handle_mouse_interaction(x_pos, y_pos, button, action)
if needs_redraw:
return display_image()
return jsonify({'success': True})
@app.route('/key-event', methods=['POST'])
def key_event():
data = request.get_json()
key = data.get('key')
needs_redraw = handle_key_press(key)
if needs_redraw:
return display_image()
return jsonify({'success': True})
@app.route('/submit', methods=['POST'])
def submit():
command = request.form['command']
needs_redraw, log = handle_command(command)
if needs_redraw:
return display_image()
return jsonify({'success': True, 'log': log})
Key Concepts for Interactive Applications
- State Tracking:
- Use
gw.redraw
to check if visualization needs updating - Use
gw.clear_buffer
to check if read buffer needs clearing
- Use
- Event Handling:
- Map UI events to appropriate
mouse_event
andkey_press
calls - Properly manage button and action states
- Map UI events to appropriate
- Command Processing:
- Use
apply_command()
to execute user commands - Retrieve command output with
flush_log()
- Use
- Responsive Rendering:
- Only redraw when necessary to improve performance
- Adjust canvas size based on viewport/display
- Multi-User Support:
- Create separate Gw instances for each user session
- Manage session lifecycle (creation, updates, cleanup)
A complete example implementing these concepts can be found in the repository at examples/flask_demo/flask_server.py
.