From 8483232bed37da3c67e3afccb9e78b1e916e4132 Mon Sep 17 00:00:00 2001 From: W Beecher Baker Date: Wed, 10 Sep 2025 13:13:23 -0400 Subject: [PATCH] Add comprehensive documentation for OTU descriptors and interactive keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created documentation suite for implementing descriptor-based filtering and identification keys in TaxonPages for the Purdue Entomological Research Collection: - DESCRIPTORS_PROJECT_INDEX.md: Main hub for all documentation - OTU_DESCRIPTORS_RESEARCH.md: Technical analysis of current state and potential - DESCRIPTOR_API_IMPLEMENTATION.md: Rails API endpoint specifications - DESCRIPTOR_UI_UX_DESIGN.md: User interface designs for semi-technical users - INTERACTIVE_KEYS_ANALYSIS.md: Analysis of identification key implementation These documents outline how to make the collection more accessible to farmers, ag extension workers, researchers, and students through structured data filtering and visual identification tools. πŸ€– Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- DESCRIPTORS_PROJECT_INDEX.md | 152 ++++++++ DESCRIPTOR_API_IMPLEMENTATION.md | 600 +++++++++++++++++++++++++++++++ DESCRIPTOR_UI_UX_DESIGN.md | 502 ++++++++++++++++++++++++++ INTERACTIVE_KEYS_ANALYSIS.md | 265 ++++++++++++++ OTU_DESCRIPTORS_RESEARCH.md | 230 ++++++++++++ 5 files changed, 1749 insertions(+) create mode 100644 DESCRIPTORS_PROJECT_INDEX.md create mode 100644 DESCRIPTOR_API_IMPLEMENTATION.md create mode 100644 DESCRIPTOR_UI_UX_DESIGN.md create mode 100644 INTERACTIVE_KEYS_ANALYSIS.md create mode 100644 OTU_DESCRIPTORS_RESEARCH.md diff --git a/DESCRIPTORS_PROJECT_INDEX.md b/DESCRIPTORS_PROJECT_INDEX.md new file mode 100644 index 0000000..30662e0 --- /dev/null +++ b/DESCRIPTORS_PROJECT_INDEX.md @@ -0,0 +1,152 @@ +# TaxonPages Descriptors Project Documentation + +## Project Overview +This project explores implementing OTU Descriptors from TaxonWorks as a richer alternative to tags for filtering the Purdue Entomological Research Collection. The goal is to serve multiple user populations (farmers, researchers, extension workers) with tailored views of the same collection data. + +## Documentation Index + +### 1. [OTU Descriptors Research](./OTU_DESCRIPTORS_RESEARCH.md) +**Purpose**: Understanding the current state and potential of descriptors + +**Key Topics**: +- What are OTU Descriptors in TaxonWorks? +- Current implementation using tags +- Advantages of descriptors over tags +- Technical architecture analysis + +**Read this if**: You need background on why we're considering descriptors + +--- + +### 2. [Descriptor API Implementation](./DESCRIPTOR_API_IMPLEMENTATION.md) +**Purpose**: Technical guide for adding descriptor endpoints to TaxonWorks + +**Key Topics**: +- Required API endpoints design +- Rails controller implementation +- JSON response formats +- Step-by-step PR guide + +**Read this if**: You're implementing the backend API changes + +--- + +### 3. [Descriptor UI/UX Design](./DESCRIPTOR_UI_UX_DESIGN.md) +**Purpose**: Making descriptors accessible to semi-technical users + +**Key Topics**: +- User personas and needs +- Progressive disclosure interface +- Mobile-responsive designs +- Natural language search +- Visual component mockups + +**Read this if**: You're designing or implementing the frontend interface + +--- + +### 4. [Interactive Keys Analysis](./INTERACTIVE_KEYS_ANALYSIS.md) +**Purpose**: Understanding and implementing identification keys + +**Key Topics**: +- Current state of keys in TaxonPages & PERC +- Multi-entry vs dichotomous keys +- UI/UX improvements for non-experts +- Data requirements and creation process +- Recommendations for PERC implementation + +**Read this if**: You're working on identification tools or creating keys + +--- + +## Quick Start Guide + +### For Project Managers +1. Start with [OTU Descriptors Research](./OTU_DESCRIPTORS_RESEARCH.md) for project rationale +2. Review [UI/UX Design](./DESCRIPTOR_UI_UX_DESIGN.md) for user experience vision +3. Check [API Implementation](./DESCRIPTOR_API_IMPLEMENTATION.md) for technical scope + +### For Backend Developers +1. Read [API Implementation](./DESCRIPTOR_API_IMPLEMENTATION.md) for code examples +2. Reference [Research](./OTU_DESCRIPTORS_RESEARCH.md) for data model understanding +3. Consider [UI/UX Design](./DESCRIPTOR_UI_UX_DESIGN.md) for API response needs + +### For Frontend Developers +1. Start with [UI/UX Design](./DESCRIPTOR_UI_UX_DESIGN.md) for interface specifications +2. Check [API Implementation](./DESCRIPTOR_API_IMPLEMENTATION.md) for available endpoints +3. Review [Research](./OTU_DESCRIPTORS_RESEARCH.md) for descriptor types + +### For UX Designers +1. Review [UI/UX Design](./DESCRIPTOR_UI_UX_DESIGN.md) for current proposals +2. Understand context in [Research](./OTU_DESCRIPTORS_RESEARCH.md) +3. See technical constraints in [API Implementation](./DESCRIPTOR_API_IMPLEMENTATION.md) + +## Key Use Cases + +### Corn Pest Identification +- **User**: Ag extension worker +- **Need**: Quick field identification +- **Solution**: Preset filter + visual size guide + damage type + +### Protected Species Check +- **User**: Researcher +- **Need**: Conservation status verification +- **Solution**: Status descriptors + location filters + +### Collection Browsing +- **User**: Student/Hobbyist +- **Need**: Educational exploration +- **Solution**: Progressive disclosure + tooltips + comparisons + +## Implementation Phases + +### Phase 1: API Development +- Add descriptor endpoints to TaxonWorks +- Test with PERC data +- Document API usage + +### Phase 2: Basic UI +- Implement core filter components +- Add preset searches +- Mobile optimization + +### Phase 3: Enhanced Features +- Natural language search +- Visual aids and guides +- Export functionality + +## Project Contacts + +- **TaxonWorks Team**: Accepting PRs, provides technical guidance +- **Purdue Team**: Defining use cases, testing with users +- **TaxonPages Development**: Frontend implementation + +## Testing Resources + +### API Testing +```bash +# Test descriptor endpoint (once implemented) +curl "https://sfg.taxonworks.org/api/v1/descriptors?project_token=ekMTicbZWijqmdpHKqs_TA" + +# Test observation filtering +curl "https://sfg.taxonworks.org/api/v1/otus/1054087/observations?project_token=ekMTicbZWijqmdpHKqs_TA" +``` + +### Sample Descriptors for PERC +- Body length (Quantitative): 0-50mm +- Host plant (Qualitative): Corn, Soybean, Wheat, etc. +- Pest status (Qualitative): Economic, Beneficial, Neutral +- Federal status (Qualitative): Endangered, Threatened, None +- Active months (Sample): January-December range + +## Next Actions + +1. **Immediate**: Review and refine descriptor categories with Purdue team +2. **Short-term**: Create TaxonWorks PR for API endpoints +3. **Medium-term**: Build Vue.js filter components +4. **Long-term**: User testing and iteration + +--- + +*Last updated: 2025-01-10* +*Project: TaxonPages Descriptor Implementation for PERC* \ No newline at end of file diff --git a/DESCRIPTOR_API_IMPLEMENTATION.md b/DESCRIPTOR_API_IMPLEMENTATION.md new file mode 100644 index 0000000..022124d --- /dev/null +++ b/DESCRIPTOR_API_IMPLEMENTATION.md @@ -0,0 +1,600 @@ +# Implementing Descriptor API Endpoints for TaxonWorks + +## Related Documents +- [OTU Descriptors Research](./OTU_DESCRIPTORS_RESEARCH.md) - Background and current state analysis +- [Descriptor UI/UX Design](./DESCRIPTOR_UI_UX_DESIGN.md) - User interface design for semi-technical users +- [Interactive Keys Analysis](./INTERACTIVE_KEYS_ANALYSIS.md) - Keys that use descriptor data + +## Overview +This document outlines the API additions needed in TaxonWorks to support descriptor-based filtering in TaxonPages, along with implementation guidance for creating a pull request. + +## Required API Endpoints + +### 1. List Descriptors +**Endpoint:** `GET /api/v1/descriptors` + +**Purpose:** Retrieve available descriptors for filtering/display + +**Query Parameters:** +- `descriptor_type` - Filter by type (qualitative, quantitative, presence_absence, etc.) +- `target` - Filter by target type (Otu, CollectionObject) +- `per` - Items per page +- `page` - Page number + +**Response Example:** +```json +[ + { + "id": 3755, + "name": "Body length", + "short_name": "length", + "type": "Descriptor::Quantitative", + "description": "Total body length in millimeters", + "position": 1 + }, + { + "id": 3756, + "name": "Host plant", + "type": "Descriptor::Qualitative", + "character_states": [ + {"id": 101, "label": "corn", "name": "Zea mays"}, + {"id": 102, "label": "soybean", "name": "Glycine max"} + ] + } +] +``` + +### 2. Get Observations for OTUs with Filtering +**Endpoint:** `GET /api/v1/otus/:id/observations` + +**Purpose:** Get all observations for an OTU, with descriptor filtering + +**Query Parameters:** +- `descriptor_ids[]` - Array of descriptor IDs to filter by +- `include_descendants` - Include observations from descendant OTUs + +**Response Example:** +```json +[ + { + "id": 809368, + "descriptor_id": 3755, + "descriptor_name": "Body length", + "type": "Observation::Quantitative", + "continuous_value": "12.5", + "continuous_unit": "mm" + } +] +``` + +### 3. Filter OTUs by Observations +**Endpoint:** `GET /api/v1/otus/filter_by_observations` + +**Purpose:** Find OTUs matching specific observation criteria + +**Query Parameters:** +- `filters[]` - Array of filter objects + +**Request Body Example:** +```json +{ + "filters": [ + { + "descriptor_id": 3755, + "type": "range", + "min": 10, + "max": 15, + "unit": "mm" + }, + { + "descriptor_id": 3756, + "type": "qualitative", + "character_state_ids": [101, 102] + }, + { + "descriptor_id": 3757, + "type": "presence", + "value": true + } + ] +} +``` + +### 4. Get Descriptor Statistics for Collection +**Endpoint:** `GET /api/v1/descriptors/:id/statistics` + +**Purpose:** Get usage statistics for a descriptor + +**Response Example:** +```json +{ + "descriptor_id": 3755, + "total_observations": 245, + "otus_observed": 89, + "value_range": {"min": 5.2, "max": 45.8}, + "common_values": [12.5, 13.0, 14.2] +} +``` + +## Implementation Code + +### Step 1: Add Routes +Add to `config/routes/api_v1.rb`: + +```ruby +# After line 139 (observations endpoints) +get '/observations', to: '/observations#api_index' +get '/observations/:id', to: '/observations#api_show' + +# Add new descriptor endpoints +get '/descriptors', to: '/descriptors#api_index' +get '/descriptors/:id', to: '/descriptors#api_show' +get '/descriptors/:id/statistics', to: '/descriptors#api_statistics' + +# Add to OTU endpoints section (after line 60) +get '/otus/:id/observations', to: '/otus#api_observations' +post '/otus/filter_by_observations', to: '/otus#api_filter_by_observations' +``` + +### Step 2: Create Descriptors Controller +Create `app/controllers/descriptors_controller.rb` (modify existing): + +```ruby +class DescriptorsController < ApplicationController + # ... existing code ... + + # Add these API methods: + + def api_index + @descriptors = Queries::Descriptor::Filter.new(params.merge(api: true)) + .all + .where(project_id: sessions_current_project_id) + .page(params[:page]) + .per(params[:per]) + + render '/descriptors/api/v1/index' + end + + def api_show + @descriptor = Descriptor.where(project_id: sessions_current_project_id) + .find(params[:id]) + + # Include character states for qualitative descriptors + if @descriptor.qualitative? + @character_states = @descriptor.character_states + end + + render '/descriptors/api/v1/show' + end + + def api_statistics + @descriptor = Descriptor.where(project_id: sessions_current_project_id) + .find(params[:id]) + + @statistics = { + descriptor_id: @descriptor.id, + total_observations: @descriptor.observations.count, + otus_observed: @descriptor.observations + .where(observation_object_type: 'Otu') + .distinct.count(:observation_object_id) + } + + # Add type-specific statistics + if @descriptor.type == 'Descriptor::Quantitative' + values = @descriptor.observations.pluck(:continuous_value).compact.map(&:to_f) + @statistics[:value_range] = { + min: values.min, + max: values.max, + mean: values.sum / values.size + } + end + + render json: @statistics + end +end +``` + +### Step 3: Add OTU Observation Methods +Add to `app/controllers/otus_controller.rb`: + +```ruby +class OtusController < ApplicationController + # ... existing code ... + + def api_observations + @otu = Otu.where(project_id: sessions_current_project_id).find(params[:id]) + + @observations = @otu.observations + + # Filter by descriptor IDs if provided + if params[:descriptor_ids].present? + @observations = @observations.where(descriptor_id: params[:descriptor_ids]) + end + + # Include descendants if requested + if params[:include_descendants] == 'true' + descendant_ids = @otu.descendants.pluck(:id) + @observations = Observation.where( + observation_object_type: 'Otu', + observation_object_id: [@otu.id] + descendant_ids + ) + end + + @observations = @observations + .includes(:descriptor) + .page(params[:page]) + .per(params[:per]) + + render '/otus/api/v1/observations' + end + + def api_filter_by_observations + filters = params[:filters] || [] + + # Start with all OTUs in project + otu_ids = Otu.where(project_id: sessions_current_project_id).pluck(:id) + + filters.each do |filter| + case filter[:type] + when 'range' + # Quantitative range filter + matching_observations = Observation + .where(descriptor_id: filter[:descriptor_id]) + .where(observation_object_type: 'Otu') + .where('continuous_value >= ? AND continuous_value <= ?', + filter[:min], filter[:max]) + + otu_ids &= matching_observations.pluck(:observation_object_id) + + when 'qualitative' + # Character state filter + matching_observations = Observation + .where(descriptor_id: filter[:descriptor_id]) + .where(observation_object_type: 'Otu') + .where(character_state_id: filter[:character_state_ids]) + + otu_ids &= matching_observations.pluck(:observation_object_id) + + when 'presence' + # Presence/absence filter + matching_observations = Observation + .where(descriptor_id: filter[:descriptor_id]) + .where(observation_object_type: 'Otu') + .where(presence: filter[:value]) + + otu_ids &= matching_observations.pluck(:observation_object_id) + end + end + + @otus = Otu.where(id: otu_ids) + .page(params[:page]) + .per(params[:per]) + + render '/otus/api/v1/index' + end +end +``` + +### Step 4: Create JSON Views +Create view files for the API responses: + +`app/views/descriptors/api/v1/index.json.jbuilder`: +```ruby +json.array! @descriptors do |descriptor| + json.id descriptor.id + json.name descriptor.name + json.short_name descriptor.short_name + json.type descriptor.type + json.description descriptor.description + json.position descriptor.position + + if descriptor.qualitative? + json.character_states descriptor.character_states do |state| + json.id state.id + json.name state.name + json.label state.label + end + end +end +``` + +`app/views/descriptors/api/v1/show.json.jbuilder`: +```ruby +json.id @descriptor.id +json.name @descriptor.name +json.short_name @descriptor.short_name +json.description @descriptor.description +json.type @descriptor.type +json.position @descriptor.position + +if @descriptor.qualitative? && @character_states + json.character_states @character_states do |state| + json.id state.id + json.name state.name + json.label state.label + json.description state.description + end +end +``` + +`app/views/otus/api/v1/observations.json.jbuilder`: +```ruby +json.array! @observations do |observation| + json.id observation.id + json.descriptor_id observation.descriptor_id + json.descriptor_name observation.descriptor.name + json.type observation.type + + case observation.type + when 'Observation::Quantitative' + json.continuous_value observation.continuous_value + json.continuous_unit observation.continuous_unit + when 'Observation::Qualitative' + json.character_state_id observation.character_state_id + json.character_state_name observation.character_state&.name + when 'Observation::PresenceAbsence' + json.presence observation.presence + when 'Observation::Sample' + json.sample_n observation.sample_n + json.sample_min observation.sample_min + json.sample_max observation.sample_max + json.sample_mean observation.sample_mean + json.sample_units observation.sample_units + end +end +``` + +## Implementation Steps for PR + +1. **Fork and Clone TaxonWorks** + ```bash + git clone https://github.com/your-username/taxonworks.git + cd taxonworks + git checkout -b feature/descriptor-api-endpoints + ``` + +2. **Implement Changes** + - Add routes to `config/routes/api_v1.rb` + - Update controllers with new API methods + - Create JSON view templates + - Add any necessary query filters in `app/queries/descriptor/filter.rb` + +3. **Test the Endpoints** + ```bash + # Start Rails server + bundle exec rails s + + # Test endpoints + curl "http://localhost:3000/api/v1/descriptors?project_token=YOUR_TOKEN" + curl "http://localhost:3000/api/v1/otus/1234/observations?project_token=YOUR_TOKEN" + ``` + +4. **Write Tests** + - Add request specs in `spec/requests/api/v1/descriptors_spec.rb` + - Test filtering logic and response formats + +5. **Create Pull Request** + - Commit with clear message explaining the feature + - Push to your fork + - Create PR with description of use case and API documentation + +## TaxonPages Integration + +Once the API is available, you can update TaxonPages: + +1. **Add API Methods** to `src/modules/otus/services/TaxonWorks.js`: +```javascript +static getDescriptors(params) { + return makeAPIRequest.get('/descriptors', { params }) +} + +static getOtuObservations(otuId, params) { + return makeAPIRequest.get(`/otus/${otuId}/observations`, { params }) +} + +static filterOtusByObservations(filters) { + return makeAPIRequest.post('/otus/filter_by_observations', { filters }) +} +``` + +2. **Create Filter Components** for different descriptor types +3. **Update Specimen Panel** to use descriptor-based filtering + +## Benefits for Purdue Use Cases + +1. **Corn Pests**: Create descriptors for: + - Host plant (qualitative) + - Damage type (qualitative) + - Economic threshold (quantitative) + - Active season (sample/range) + +2. **Protected Species**: Create descriptors for: + - Conservation status (qualitative) + - Population trend (qualitative) + - Habitat requirements (qualitative) + - Last observation date (quantitative/date) + +3. **Research Specimens**: Create descriptors for: + - Collection method (qualitative) + - Preservation type (qualitative) + - DNA extracted (presence/absence) + - Loan availability (presence/absence) + +This approach provides structured, queryable data that's much richer than simple tags while maintaining flexibility for different user groups. + +## Integration with Interactive Keys + +### Shared API Infrastructure + +The descriptor API endpoints support both filtering AND interactive keys: + +1. **Observation Matrices as Keys** + - The same matrices used for descriptors become interactive keys + - Existing endpoint: `GET /api/v1/observation_matrices/:id/key` + - Already returns descriptor data formatted for keys + +2. **Unified Data Model** + ```ruby + # Same descriptor serves multiple purposes: + descriptor = Descriptor.find(3755) + + # For filtering: + observations = descriptor.observations.where(observation_object_type: 'Otu') + + # For keys: + key_data = { + descriptor_id: descriptor.id, + states: descriptor.character_states, + usefulness: descriptor.calculate_usefulness # For ordering in keys + } + ``` + +3. **Enhanced Endpoints for Both Uses** + + Add to the descriptor API to support key generation: + + ```ruby + # app/controllers/descriptors_controller.rb + + def api_key_usefulness + # Calculate which descriptors are most useful for identification + @descriptors = Descriptor + .where(project_id: sessions_current_project_id) + .includes(:observations) + .map do |d| + { + id: d.id, + name: d.name, + usefulness: calculate_usefulness(d), # Shannon entropy or similar + coverage: d.observations.distinct.count(:observation_object_id) + } + end + .sort_by { |d| -d[:usefulness] } + + render json: @descriptors + end + + private + + def calculate_usefulness(descriptor) + # Calculate how well this descriptor divides the remaining taxa + # Higher score = better at splitting groups evenly + observations = descriptor.observations + return 0 if observations.empty? + + # Shannon entropy calculation + total = observations.count.to_f + groups = observations.group(:character_state_id).count + + entropy = groups.values.sum do |count| + proportion = count / total + -(proportion * Math.log2(proportion)) + end + + entropy * Math.sqrt(groups.size) # Favor descriptors with more states + end + ``` + +### API Routes for Key Support + +Add these routes to support key creation and management: + +```ruby +# config/routes/api_v1.rb + +# Descriptor endpoints that support both filtering and keys +get '/descriptors/key_candidates', to: '/descriptors#api_key_candidates' +get '/descriptors/:id/usefulness', to: '/descriptors#api_usefulness' + +# Matrix endpoints for key generation +post '/observation_matrices/generate_from_descriptors', to: '/observation_matrices#api_generate' +get '/observation_matrices/:id/optimal_sequence', to: '/observation_matrices#api_optimal_sequence' +``` + +### Creating Keys from Descriptors + +Allow automatic key generation from filtered descriptors: + +```ruby +# app/controllers/observation_matrices_controller.rb + +def api_generate + # Generate a matrix/key from selected descriptors + descriptor_ids = params[:descriptor_ids] + otu_ids = params[:otu_ids] || Otu.where(project_id: sessions_current_project_id).pluck(:id) + + @matrix = ObservationMatrix.create!( + name: params[:name], + project_id: sessions_current_project_id + ) + + # Add descriptors as columns + descriptor_ids.each_with_index do |d_id, index| + ObservationMatrixColumn.create!( + observation_matrix: @matrix, + descriptor_id: d_id, + position: index + ) + end + + # Add OTUs as rows + otu_ids.each_with_index do |otu_id, index| + ObservationMatrixRow.create!( + observation_matrix: @matrix, + observation_object_type: 'Otu', + observation_object_id: otu_id, + position: index + ) + end + + render json: { + matrix_id: @matrix.id, + interactive_key_url: "/api/v1/observation_matrices/#{@matrix.id}/key" + } +end +``` + +### Response Format for Dual Use + +Structure responses to support both filtering and key interfaces: + +```json +{ + "descriptor": { + "id": 3755, + "name": "Body length", + "type": "Descriptor::Quantitative", + + // For filtering UI: + "filter_config": { + "input_type": "range", + "min": 0, + "max": 50, + "unit": "mm", + "step": 0.5 + }, + + // For key UI: + "key_config": { + "usefulness": 3.2, + "coverage": 0.85, + "position": 1, + "show_by_default": true + }, + + // Shared data: + "observations_count": 145, + "otus_scored": 89 + } +} +``` + +### Benefits of Integrated Implementation + +1. **Single Data Entry**: Score once, use for both browsing and identification +2. **Consistent Vocabulary**: Same terms across all interfaces +3. **Automatic Key Updates**: As new observations are added, keys improve +4. **Progressive Identification**: Filter first, then use targeted keys +5. **Learning Pathway**: Browsing teaches vocabulary needed for keys + +This integrated approach means implementing descriptors automatically provides the foundation for better identification keys, making both systems more valuable to users. \ No newline at end of file diff --git a/DESCRIPTOR_UI_UX_DESIGN.md b/DESCRIPTOR_UI_UX_DESIGN.md new file mode 100644 index 0000000..2a4b128 --- /dev/null +++ b/DESCRIPTOR_UI_UX_DESIGN.md @@ -0,0 +1,502 @@ +# Descriptor-Based Filtering: UI/UX Design for Semi-Technical Users + +## Related Documents +- [OTU Descriptors Research](./OTU_DESCRIPTORS_RESEARCH.md) - Technical background and current state +- [Descriptor API Implementation](./DESCRIPTOR_API_IMPLEMENTATION.md) - Backend implementation details +- [Interactive Keys Analysis](./INTERACTIVE_KEYS_ANALYSIS.md) - Identification keys using descriptors + +## User Personas & Needs + +### Primary Users +1. **Ag Extension Workers**: Need quick pest identification for farmer consultations +2. **Farmers**: Looking for practical pest management information +3. **Researchers**: Need precise specimen data for studies +4. **Grad Students**: Learning taxonomy, need educational scaffolding +5. **Entomology Hobbyists**: Want to explore and learn about local species +6. **Agronomists**: Need crop-pest relationship data + +### Key Design Principles + +1. **Progressive Disclosure**: Start simple, reveal complexity as needed +2. **Natural Language**: Use terms familiar to users, not database jargon +3. **Visual Feedback**: Show what's happening with filters in real-time +4. **Smart Defaults**: Pre-populate common searches for each user group +5. **Mobile-First**: Many ag extension workers use tablets/phones in the field + +## UI Component Designs + +### 1. Filter Panel Header +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ πŸ” Find Specimens By: β”‚ +β”‚ β”‚ +β”‚ [Quick Filters β–Ό] [Physical Traits β–Ό] [Habitat β–Ό] [Status β–Ό]β”‚ +β”‚ β”‚ +β”‚ Currently showing: 245 of 1,847 specimens β”‚ +β”‚ [Clear all filters] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### 2. Quick Filters (Presets for Common Searches) +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Quick Filters β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Popular searches: β”‚ +β”‚ β”‚ +β”‚ 🌽 [Corn Pests] 🌱 [Soybean Pests] 🚨 [Protected Species] β”‚ +β”‚ πŸ“ [Found in Indiana] 🏑 [Garden Pests] 🌾 [Field Crops] β”‚ +β”‚ β”‚ +β”‚ Or build your own filter below... β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### 3. Physical Traits (Quantitative Descriptors) +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Physical Traits β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Size: β”‚ +β”‚ [Tiny (<5mm)] [Small (5-10mm)] [Medium (10-20mm)] [Large] β”‚ +β”‚ β”‚ +β”‚ Or specify exact range: β”‚ +β”‚ [5 ] mm to [15 ] mm β”‚ +β”‚ β”‚ +β”‚ Wing type: β”‚ +β”‚ β—‹ Any β—‹ Winged β—‹ Wingless β—‹ Reduced wings β”‚ +β”‚ β”‚ +β”‚ Color (check all that apply): β”‚ +β”‚ ☐ Black ☐ Brown ☐ Green ☐ Red ☐ Yellow β”‚ +β”‚ ☐ Metallic ☐ Striped ☐ Spotted β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### 4. Habitat/Host (Qualitative Descriptors) +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Habitat & Host Plants β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Where to find: β”‚ +β”‚ β”‚ +β”‚ Common crops: β”‚ +β”‚ ☐ Corn ☐ Soybean ☐ Wheat ☐ Alfalfa ☐ Vegetables β”‚ +β”‚ β”‚ +β”‚ Habitat type: β”‚ +β”‚ ☐ Agricultural fields ☐ Gardens ☐ Forest β”‚ +β”‚ ☐ Grassland ☐ Wetland ☐ Urban areas β”‚ +β”‚ β”‚ +β”‚ Damage type: β”‚ +β”‚ ☐ Leaf feeding ☐ Root damage ☐ Fruit boring β”‚ +β”‚ ☐ Stem boring ☐ Sap sucking ☐ Seed feeding β”‚ +β”‚ β”‚ +β”‚ Active season: β”‚ +β”‚ [Spring][Summer][Fall][Winter] or β”‚ +β”‚ Months: [May β–Ό] to [September β–Ό] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### 5. Conservation Status (Special Descriptors) +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Conservation & Management Status β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Protection status: β”‚ +β”‚ ☐ Federally endangered ☐ Federally threatened β”‚ +β”‚ ☐ State protected ☐ Species of concern β”‚ +β”‚ β”‚ +β”‚ Pest status: β”‚ +β”‚ ☐ Economic pest ☐ Quarantine pest ☐ Invasive species β”‚ +β”‚ ☐ Beneficial insect ☐ Pollinator β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### 6. Active Filter Display (Pills/Tags) +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Active filters: β”‚ +β”‚ β”‚ +β”‚ [Size: 5-15mm Γ—] [Host: Corn Γ—] [Active: May-Sept Γ—] β”‚ +β”‚ [Pest status: Economic Γ—] β”‚ +β”‚ β”‚ +β”‚ 47 specimens match your criteria β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Smart Features for Accessibility + +### 1. Natural Language Search Bar +Instead of just filters, offer a search box that understands phrases: +- "corn pests active in summer" +- "small beetles on soybeans" +- "protected species in Indiana" +- "insects larger than 20mm" + +### 2. Visual Size Reference +``` +Actual size reference: +[Β·] Rice grain [●] Pea [β—‰] Dime [β—Ž] Quarter + 3mm 7mm 17mm 24mm +``` + +### 3. Tooltips with Examples +Hover over any filter to see: +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Leaf feeding damage: β”‚ +β”‚ Insects that chew holes in β”‚ +β”‚ leaves or skeletonize them. β”‚ +β”‚ β”‚ +β”‚ Examples: Japanese beetles, β”‚ +β”‚ caterpillars, grasshoppers β”‚ +β”‚ [Show photos] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### 4. Seasonal Calendar Widget +``` +When are they active? (click months) +Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec +[ ][ ][ ][βœ“][βœ“][βœ“][βœ“][βœ“][βœ“][ ][ ][ ] +``` + +### 5. "Did You Mean?" Suggestions +When filters return few/no results: +``` +No exact matches found for your criteria. + +Did you mean to search for: +β€’ Corn pests of ANY size? (127 results) +β€’ Soybean pests 5-15mm? (84 results) +β€’ All pests active in May-September? (342 results) +``` + +## Mobile-Responsive Design + +### Phone View (Collapsed) +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ πŸ” Find: 3 activeβ”‚ +β”‚ [Tap to modify] β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ 47 specimens β”‚ +β”‚ β”‚ +β”‚ [Specimen 1] β”‚ +β”‚ [Specimen 2] β”‚ +β”‚ [Specimen 3] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Phone View (Expanded Filters) +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ ← Back β”‚ +β”‚ β”‚ +β”‚ Quick Presets: β”‚ +β”‚ [Corn Pests] β”‚ +β”‚ [Protected] β”‚ +β”‚ β”‚ +β”‚ Size: β”‚ +β”‚ ● Small (5-10mm)β”‚ +β”‚ β”‚ +β”‚ Host Plant: β”‚ +β”‚ β˜‘ Corn β”‚ +β”‚ ☐ Soybean β”‚ +β”‚ β”‚ +β”‚ [Apply Filters] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## User Flow Examples + +### Farmer Looking for Pest ID +1. Clicks "Corn Pests" preset +2. Sees all corn pests +3. Narrows by size: "Medium (10-20mm)" +4. Narrows by damage: "Leaf feeding" +5. Gets 3-5 likely candidates with photos + +### Extension Worker in Field +1. Opens mobile site +2. Taps "Quick ID" +3. Selects: Crop β†’ Corn +4. Selects: Damage type β†’ Root damage +5. Selects: Time of year β†’ Current month auto-selected +6. Gets short list with management recommendations + +### Researcher Finding Specimens +1. Starts with "Advanced Search" +2. Enters precise measurements: "12.5-13.5mm" +3. Selects multiple character states +4. Adds collection date range +5. Exports results as CSV with DOI citations + +## Vue.js Component Structure + +```vue + + +``` + +## Accessibility Features + +1. **Keyboard Navigation**: All filters accessible via Tab +2. **Screen Reader Support**: Proper ARIA labels +3. **High Contrast Mode**: Clear boundaries and labels +4. **Text Scaling**: Responsive to browser zoom +5. **Color Blind Friendly**: Don't rely on color alone + +## Performance Considerations + +1. **Lazy Loading**: Load descriptors as sections expand +2. **Debounced Search**: Wait 300ms after typing stops +3. **Result Preview**: Show count before applying filters +4. **Cached Filters**: Remember user's last search +5. **Progressive Enhancement**: Work without JavaScript + +## Educational Components + +### Inline Learning +``` +ℹ️ What's an "economic pest"? +An insect that causes enough crop damage to result in +economic loss if not controlled. The threshold varies +by crop value and control costs. [Learn more] +``` + +### Visual Comparison Tool +``` +Compare similar species: +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Bean β”‚ Mexican β”‚ Spotted β”‚ +β”‚ Leaf β”‚ Bean β”‚ Cucumberβ”‚ +β”‚ Beetle β”‚ Beetle β”‚ Beetle β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ [Photo] β”‚ [Photo] β”‚ [Photo] β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β€’ 6mm β”‚ β€’ 7mm β”‚ β€’ 6mm β”‚ +β”‚ β€’ Yellowβ”‚ β€’ Orangeβ”‚ β€’ Yellowβ”‚ +β”‚ β€’ 16spotsβ”‚β€’ 16spotsβ”‚β€’ 12spotsβ”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Implementation Priority + +### Phase 1: Core Filtering (MVP) +- Quick preset filters +- Basic size/color filters +- Host plant selection +- Simple results display + +### Phase 2: Enhanced Usability +- Natural language search +- Visual size guides +- Mobile optimization +- Filter suggestions + +### Phase 3: Advanced Features +- Comparison tools +- Seasonal calendars +- Export functionality +- Saved searches + +## Testing with Users + +### Usability Testing Protocol +1. Give users common scenarios: + - "Find pests affecting your corn crop" + - "Identify a 15mm beetle found on soybeans" + - "Check if this insect is protected" + +2. Measure: + - Time to complete task + - Number of clicks/taps + - Error recovery + - User satisfaction + +3. A/B Test: + - Preset filters vs. manual selection + - Icon-based vs. text-based options + - Collapsed vs. expanded initial state + +## Success Metrics + +1. **Efficiency**: Average time to find target specimen <30 seconds +2. **Accuracy**: Correct identification rate >80% +3. **Engagement**: Users apply 2-3 filters on average +4. **Accessibility**: WCAG 2.1 AA compliance +5. **Mobile Usage**: 40%+ of searches from mobile devices + +## Integration with Interactive Keys + +### Synergy Between Descriptors and Keys + +The descriptor system and interactive keys share the same underlying data model, creating powerful synergies: + +1. **Shared Data Infrastructure** + - Descriptors used for filtering ARE the characters in multi-entry keys + - Same scoring/observation data serves both purposes + - One data entry effort, multiple user interfaces + +2. **Progressive Identification Flow** + ``` + Browse Collection β†’ Filter by Descriptors β†’ Narrow to Group β†’ Use Key for Species + + Example: + 1. Filter: "Corn pests, 10-15mm" β†’ 25 specimens + 2. Launch: "Corn Pest Identification Key" β†’ Precise species ID + ``` + +3. **Unified Visual Language** + - Same icons, photos, and terminology across filters and keys + - Users learn once, apply everywhere + - Consistent size references, color swatches, etc. + +### Key-Specific UI Components + +#### Interactive Key Launcher +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Need help identifying this specimen? β”‚ +β”‚ β”‚ +β”‚ Based on your filters, try these keys: β”‚ +β”‚ [πŸ” Corn Pest Visual Key] - Best for field use β”‚ +β”‚ [πŸ“‹ Beetle Multi-Entry Key] - Most comprehensive β”‚ +β”‚ [🌳 Garden Pest Decision Tree] - Step-by-step β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +#### Embedded Mini-Key Widget +For quick identification without leaving the browse interface: +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Quick ID Helper [Expand] β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Answer 2-3 questions to narrow your search: β”‚ +β”‚ β”‚ +β”‚ 1. Where did you find it? β”‚ +β”‚ [Field] [Garden] [Storage] [House] β”‚ +β”‚ β”‚ +β”‚ 2. What damage do you see? β”‚ +β”‚ [Holes in leaves] [Wilting] [Root damage] [None] β”‚ +β”‚ β”‚ +β”‚ β†’ Showing 3 likely matches... β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Dichotomous Key Visualization +Transform traditional text-based keys into visual decision trees: + +``` + Insect on corn? + / \ + Yes No β†’ [Other crop keys] + | + Damage to leaves? + / \ + Yes No + | | + Holes visible? Check roots + / \ | + Yes No [Root pest key] + | | +[Corn borer] [Aphids] +``` + +### Multi-Entry Key Enhancement +Make character selection more intuitive: + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Select What You Can See: β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ βœ“ Size: Medium (10-20mm) [Why this matters] β”‚ +β”‚ βœ“ Wings: Present [Why this matters] β”‚ +β”‚ ? Color: [Not sure] [Show color guide] β”‚ +β”‚ β”‚ +β”‚ Remaining possibilities: 8 of 45 β”‚ +β”‚ Most likely: Western Corn Rootworm (matches 2/2 traits) β”‚ +β”‚ β”‚ +β”‚ [Show me what to look for next] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Mobile Key Interface +Optimized for field use: + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Field ID Mode β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ [Take Photo] β”‚ +β”‚ β”‚ +β”‚ Compare to: β”‚ +β”‚ β”Œβ”€β”€β”€β” β”Œβ”€β”€β”€β” β”‚ +β”‚ β”‚[A]β”‚ β”‚[B]β”‚ β”‚ +β”‚ β””β”€β”€β”€β”˜ β””β”€β”€β”€β”˜ β”‚ +β”‚ β”Œβ”€β”€β”€β” β”Œβ”€β”€β”€β” β”‚ +β”‚ β”‚[C]β”‚ β”‚[D]β”‚ β”‚ +β”‚ β””β”€β”€β”€β”˜ β””β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ [More details] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Bridging Browsing and Identification + +1. **Smart Handoffs** + - "Can't find what you're looking for? Try our identification key" + - "Found multiple matches? Use the key to distinguish between them" + +2. **Contextual Key Suggestions** + - Recommend keys based on active filters + - Highlight most relevant key for current search results + +3. **Learning Mode** + - Keys teach descriptor vocabulary + - Descriptors prepare users for key terminology + +### Implementation Priority for Keys + +#### Phase 1: Visual Keys (Highest Impact) +- Photo-based dichotomous keys for top 20 pests +- Simple language, no technical terms +- Mobile-optimized interface + +#### Phase 2: Smart Multi-Entry Keys +- Auto-suggest most useful characters +- Show photo examples for each state +- Confidence scoring ("90% match") + +#### Phase 3: Integrated Experience +- Seamless flow between browsing and keys +- Unified observation data +- Cross-training between interfaces + +## Next Steps + +1. Create interactive prototype in Figma/Adobe XD +2. Conduct user interviews with each persona group +3. Build Vue.js component library +4. Implement Phase 1 features +5. Iterate based on user feedback +6. **Develop pilot keys for testing with extension workers** +7. **Create visual assets library for keys and descriptors** + +--- + +*This document is part of the TaxonPages descriptor implementation project. See related documents for technical implementation details.* \ No newline at end of file diff --git a/INTERACTIVE_KEYS_ANALYSIS.md b/INTERACTIVE_KEYS_ANALYSIS.md new file mode 100644 index 0000000..b5199b9 --- /dev/null +++ b/INTERACTIVE_KEYS_ANALYSIS.md @@ -0,0 +1,265 @@ +# Interactive Keys Analysis for TaxonPages & PERC + +## Related Documents +- [Descriptors Project Index](./DESCRIPTORS_PROJECT_INDEX.md) - Main project documentation hub +- [OTU Descriptors Research](./OTU_DESCRIPTORS_RESEARCH.md) - Background on descriptors which power multi-entry keys +- [Descriptor UI/UX Design](./DESCRIPTOR_UI_UX_DESIGN.md) - UI considerations that apply to keys + +## Executive Summary + +TaxonPages **already supports** both types of TaxonWorks keys, but PERC has **minimal key data** currently: +- Only 2 observation matrices exist ("Cerotoma revision" and "Experimental matrix") +- Most OTUs have no associated keys +- The infrastructure works but needs content creation + +## Current Implementation Status + +### TaxonPages Support βœ… + +TaxonPages has full support for both key types: + +1. **Multi-Entry Keys** (Interactive Keys) + - Component: `src/modules/interactiveKeys/views/InteractiveKey.vue` + - Uses `@sfgrp/distinguish` package + - Route: `/interactive-keys/:id` + - Powered by observation matrices with descriptors + +2. **Dichotomous Keys** (Standard Keys) + - Component: `src/modules/keys/views/keyId.vue` + - Uses `@sfgrp/pinpoint` package + - Route: `/keys/:id` + - Traditional couplet-based navigation + +3. **Keys Panel** on OTU Pages + - Shows available keys for each taxon + - Location: `src/modules/otus/components/Panel/PanelKeys/PanelKeys.vue` + - Displays both "scoped" (specific to OTU) and "in" (includes OTU) keys + +### TaxonWorks API Support βœ… + +Working endpoints found: +- `GET /api/v1/otus/:id/inventory/keys` - Lists keys for an OTU +- `GET /api/v1/observation_matrices/:id/key` - Gets multi-entry key data +- `GET /api/v1/observation_matrices` - Lists available matrices +- `GET /api/v1/leads/key/:id` - Gets dichotomous key data (needs valid lead ID) + +### PERC Data Status ⚠️ + +Current state of PERC collection: +- **2 observation matrices total**: + - "Cerotoma revision" (ID: 261) - Has descriptors and states + - "Experimental matrix" (ID: 294) - Unknown content +- **Most OTUs have no keys** - Tested several, all returned empty +- **One working example**: Cerotoma sp 1 (OTU 1054087) is in matrix 261 + +## How Keys Work in TaxonWorks + +### Multi-Entry Keys (Matrix-Based) +``` +Observation Matrix + ↓ +Contains Descriptors (characters) + ↓ +Each Descriptor has States (character states) + ↓ +OTUs/Specimens scored for each Descriptor + ↓ +User selects states β†’ System eliminates non-matching taxa +``` + +**Example from PERC's Cerotoma matrix**: +- Descriptor: "Armature" (head armature) +- States: None, Tubercles, 2 spines, etc. +- Usefulness: 2.41 (algorithmically calculated) + +### Dichotomous Keys (Lead-Based) +``` +Starting Lead (root) + ↓ +Couplet with 2+ choices + ↓ +Each choice leads to: + - Another couplet (lead) + - OR Terminal taxon (OTU) + ↓ +Linear path to identification +``` + +## UI/UX Considerations for Semi-Technical Users + +### Current Interface Strengths +1. **Visual hierarchy** - Clear progression through choices +2. **Backtracking** - Can go back to previous decisions +3. **Progress tracking** - Shows eliminated vs remaining taxa +4. **Direct links** - Taxa link to their pages + +### Needed Improvements for Target Users + +#### For Multi-Entry Keys +1. **Plain language descriptors** + - Current: "Sulcus in prothorax" + - Better: "Groove in front body segment" + +2. **Visual aids** + - Add images for each character state + - Size references and comparison tools + - Hover tooltips with examples + +3. **Smart ordering** + - Most useful characters first (by usefulness score) + - Group related characters + - Hide advanced characters initially + +4. **Progress feedback** + ``` + You've eliminated 45 of 52 possibilities + Remaining: 7 species + Most likely: [Species A] (matches 5/5 selected traits) + ``` + +#### For Dichotomous Keys +1. **Visual couplets** + ``` + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Wings fully developed β”‚ OR β”‚ Wings reduced/absent β”‚ + β”‚ [Photo of winged] β”‚ β”‚ [Photo of wingless] β”‚ + β”‚ β†’ Go to 2 β”‚ β”‚ β†’ Go to 8 β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ``` + +2. **Breadcrumb trail** + ``` + Path taken: Start β†’ Wings present β†’ Size >10mm β†’ Color metallic β†’ Result + [Click any step to go back] + ``` + +3. **Confidence indicators** + - "⚠️ This choice point is critical - look carefully" + - "ℹ️ If unsure, this is the more common option" + +## Recommendations for PERC + +### Phase 1: Create Foundation Keys (Quick Wins) +Build simple keys for common user needs: + +1. **"Common Garden Pests" Key** + - 10-15 most common species + - Simple visual characters (size, color, shape) + - Photos for every choice + +2. **"Corn Field Insects" Key** + - Focus on economically important species + - Include damage type as character + - Link to management recommendations + +3. **"Is This Protected?" Quick Key** + - Yes/no dichotomous key + - Federal and state protected species + - Clear visual distinctions + +### Phase 2: Build Comprehensive Matrix +Create observation matrix for major groups: + +1. **Select initial target group** (e.g., beetles of agricultural importance) +2. **Define 15-20 simple descriptors**: + - Size categories + - Color patterns + - Host plants + - Habitat preferences + - Seasonal activity +3. **Score all relevant OTUs** +4. **Add photographs** for each state + +### Phase 3: Enhanced User Experience +1. **Create mobile-optimized version** +2. **Add "learning mode"** with explanations +3. **Implement confidence scoring** +4. **Build comparison tools** + +## Technical Implementation Notes + +### Creating Keys in TaxonWorks + +#### For Multi-Entry Keys: +1. Create observation matrix +2. Add descriptors (these become the filterable characters) +3. Define character states for each descriptor +4. Score OTUs for each character +5. Matrix automatically becomes available as interactive key + +#### For Dichotomous Keys: +1. Create root lead +2. Add couplets with descriptive text +3. Link each choice to either: + - Another lead (continue key) + - An OTU (terminal identification) +4. Add images and notes as needed + +### Data Entry Efficiency Tips +- Use batch operations for scoring common characters +- Import existing keys from other formats +- Collaborate with experts for specific groups +- Start with most economically important species + +## Example API Responses + +### Key Inventory for an OTU +```json +{ + "observation_matrices": { + "scoped": {}, // Keys specifically for this OTU + "in": { // Keys that include this OTU + "261": "Cerotoma revision" + } + }, + "leads": { + "scoped": {}, // Dichotomous keys for this OTU + "in": {} // Dichotomous keys including this OTU + } +} +``` + +### Multi-Entry Key Structure +```json +{ + "descriptor": { + "id": 3749, + "name": "Armature", + "usefulness": 2.41, // Higher = more discriminating + "states": [ + { + "id": 10042, + "name": "None", + "number_of_objects": 2 // 2 OTUs have this state + } + ] + } +} +``` + +## Success Metrics + +1. **Coverage**: % of economically important species in keys +2. **Accuracy**: Correct identification rate by users +3. **Speed**: Average time to identification +4. **Accessibility**: Success rate for non-experts +5. **Mobile usage**: % of key uses on mobile devices + +## Next Steps + +1. **Audit existing species** to identify key gaps +2. **Prioritize groups** for key development +3. **Create descriptor vocabulary** appropriate for users +4. **Build pilot key** for testing with extension workers +5. **Gather feedback** and iterate + +## Resources + +- TaxonWorks Keys Documentation: https://docs.taxonworks.org/guide/Manual/Keys/ +- Distinguish (multi-entry): https://github.com/SpeciesFileGroup/distinguish +- Pinpoint (dichotomous): https://github.com/SpeciesFileGroup/pinpoint +- Example working key: https://sfg.taxonworks.org/api/v1/observation_matrices/261/key + +--- + +*This analysis is part of the TaxonPages enhancement project for PERC. The goal is to make taxonomic identification accessible to farmers, extension workers, and researchers.* \ No newline at end of file diff --git a/OTU_DESCRIPTORS_RESEARCH.md b/OTU_DESCRIPTORS_RESEARCH.md new file mode 100644 index 0000000..3d9db72 --- /dev/null +++ b/OTU_DESCRIPTORS_RESEARCH.md @@ -0,0 +1,230 @@ +# OTU Descriptors Research for Collection Browsing + +## Related Documents +- [Descriptor API Implementation](./DESCRIPTOR_API_IMPLEMENTATION.md) - Rails API endpoint specifications and code +- [Descriptor UI/UX Design](./DESCRIPTOR_UI_UX_DESIGN.md) - User interface design for semi-technical users +- [Interactive Keys Analysis](./INTERACTIVE_KEYS_ANALYSIS.md) - How descriptors power identification keys + +## Context +The Purdue Entomological Research Collection (PERC) is using TaxonPages to serve their collection data from TaxonWorks. While TaxonPages is primarily designed for taxonomy management, Purdue wants to use it for collection browsing to serve multiple user populations: + +- **Ag Extension workers** helping farmers identify pests +- **Researchers** concerned with protected species +- **Taxonomists** interested in species identification +- **General users** browsing the collection + +The challenge is serving different views of the same collection to different audiences. The team has been using tags (e.g., "corn pests", "federally protected species") but is exploring OTU Descriptors as a potentially richer solution. + +## What are OTU Descriptors? + +OTU (Operational Taxonomic Unit) Descriptors in TaxonWorks are a sophisticated system for recording structured observations about biological specimens and taxa. + +### Key Concepts + +**OTUs** (../taxonworks/app/models/otu.rb:1-24) +- Units of study in TaxonWorks, usually representing taxa +- Can be linked to a TaxonName or given arbitrary labels +- N:1 relationship with taxa (multiple OTUs can point to the same taxon) + +**Descriptors** (../taxonworks/app/models/descriptor.rb:2-10) +- Define classes of observations that can be made about OTUs or Collection Objects +- Come in various types reflecting different data recording approaches +- Located in ../taxonworks/app/models/descriptor/ with subtypes: + - `qualitative.rb` - Character/state expressions + - `continuous.rb` / `sample.rb` - Quantitative measurements + - `presence_absence.rb` - Binary traits + - `working.rb` - Raw notes/observations + - `media.rb` - Visual observations + - `gene.rb` - Genetic data + +**Observations** (../taxonworks/app/models/observation.rb:1-5) +- Record the actual data for a descriptor on a specific OTU or Collection Object +- Link descriptors to biological entities +- Stored individually, not as complete matrices + +### Data Model Architecture + +From TaxonWorks documentation (https://docs.taxonworks.org/guide/Manual/matrices.html): +- Matrices consist of Rows (OTUs/Collection Objects) and Columns (Descriptors) +- Same OTU or descriptor can be used across multiple matrices +- Observations are stored per cell, maintaining consistency across matrices + +## Current Implementation Status + +### TaxonPages (This Repository) + +**Current Tag-based Filtering:** +- Implemented in `src/modules/otus/components/Panel/PanelSpecimens/PanelSpecimens.vue:67-72` +- Uses `MultiSelectTags` component for filtering specimens +- Tags fetched via `TaxonWorks.getAllTags()` and `TaxonWorks.getKeywords()` (src/modules/otus/services/TaxonWorks.js:142-168) +- Simple keyword-based filtering system + +**No Descriptor Integration:** +- No API calls to descriptor endpoints +- No UI components for descriptor-based filtering +- No observation data consumption + +### TaxonWorks API + +**Available Endpoints:** +- `/api/v1/observations` - Working, returns observation data +- `/api/v1/otus/{id}` - Returns OTU information +- Various tag/keyword endpoints for current filtering + +**Missing/Not Public:** +- `/api/v1/descriptors` - Returns "Invalid route" +- No public endpoints for creating/managing descriptors +- No endpoints for descriptor-based filtering of OTUs + +**Example Observation Data** (from API): +```json +{ + "id": 809368, + "descriptor_id": 3755, + "observation_object_id": 1054087, + "observation_object_type": "Otu", + "type": "Observation::PresenceAbsence", + "presence": true, + "object_label": "Third and fourth antennomeres modified: present on Cerotoma sp 1 (maculata)" +} +``` + +## Potential Use Cases for Descriptors + +### Advantages Over Tags + +1. **Structured Data**: Instead of "corn pest" tag, could have: + - Host plant: corn (qualitative descriptor) + - Damage type: leaf feeding (qualitative) + - Economic threshold: 5 per plant (quantitative) + +2. **Multi-dimensional Filtering**: Complex queries like: + - "Show specimens with body length 10-15mm AND found on corn AND active May-July" + +3. **User-specific Views**: Different descriptor sets for different audiences: + - **Ag Extension**: crop damage patterns, pesticide resistance, economic thresholds + - **Conservation**: federal status, habitat requirements, population trends + - **Taxonomists**: morphological measurements, type specimen data + +4. **Quantitative Queries**: Range-based searches impossible with tags: + - "Specimens 5-10mm in length" + - "Species active above 20Β°C" + +## Implementation Considerations + +### Required Work + +1. **TaxonWorks API Development**: + - Expose descriptor endpoints publicly + - Add descriptor-based filtering to OTU/specimen queries + - Document descriptor API usage + +2. **TaxonPages Frontend**: + - New components for descriptor-based filtering UI + - Handle different descriptor types (qualitative vs quantitative) + - Integrate with existing specimen display + +3. **Data Entry**: + - Create relevant descriptors for use cases + - Populate observations for existing specimens + - Establish controlled vocabularies + +### Current Workarounds + +While waiting for full descriptor support: +- Continue using tag system for simple categorization +- Consider hierarchical tags to simulate structure +- Document desired descriptors for future implementation + +## Technical References + +### Key Files for Future Work + +**TaxonPages:** +- `src/modules/otus/services/TaxonWorks.js` - API service layer +- `src/modules/otus/components/Panel/PanelSpecimens/PanelSpecimens.vue` - Specimen filtering UI +- `src/modules/otus/composables/useSpecimenTags.js` - Current tag handling + +**TaxonWorks:** +- `app/models/descriptor.rb` - Descriptor model +- `app/models/observation.rb` - Observation model +- `app/models/otu.rb` - OTU model +- `app/controllers/descriptors_controller.rb` - Descriptor controller (not exposed to API) + +### API Testing Commands + +```bash +# Get observations for an OTU +curl "https://sfg.taxonworks.org/api/v1/observations?project_token=ekMTicbZWijqmdpHKqs_TA&observation_object_type=Otu&observation_object_id=1054087" + +# Get OTU details +curl "https://sfg.taxonworks.org/api/v1/otus/1054087?project_token=ekMTicbZWijqmdpHKqs_TA" + +# Test descriptor endpoint (currently returns "Invalid route") +curl "https://sfg.taxonworks.org/api/v1/descriptors?project_token=ekMTicbZWijqmdpHKqs_TA" +``` + +## Relationship to Interactive Keys + +### Shared Data Model +Descriptors and interactive keys are deeply interconnected in TaxonWorks: + +1. **Multi-Entry Keys ARE Descriptor Matrices** + - The same observation matrix that stores descriptor data becomes an interactive key + - Each descriptor becomes a filterable character in the key + - Character states in descriptors become the selectable options in keys + +2. **Data Entry Once, Use Everywhere** + ``` + Create Descriptor β†’ Score OTUs β†’ Use for: + - Collection browsing/filtering + - Multi-entry identification keys + - Data analysis and reporting + - Specimen comparison + ``` + +3. **Progressive Refinement** + - Start with broad descriptor-based filtering to narrow to a group + - Then use detailed keys for precise species identification + - Example: Filter to "corn pests" β†’ Launch corn pest key β†’ Identify exact species + +### Implementation Synergies + +When implementing descriptors for Purdue's use cases, you're simultaneously building: + +1. **Filter System**: Browse collection by traits +2. **Identification Keys**: Step users through identification +3. **Educational Content**: Teach morphology and terminology +4. **Data Foundation**: Enable future analyses and visualizations + +### Key Creation Benefits from Descriptors + +Creating descriptors for filtering automatically provides: +- Characters for multi-entry keys +- Standardized vocabulary across the system +- Scored observations ready for key generation +- Photo associations for visual keys + +Example workflow: +1. Create "Host plant" descriptor with states: Corn, Soybean, Wheat +2. Score all pest OTUs for their host plants +3. This data now works for: + - Filtering: "Show all corn pests" + - Keys: "What crops does it attack?" β†’ Corn β†’ [narrowed list] + +## Next Steps + +1. **Collaborate with TaxonWorks team** on exposing descriptor API endpoints +2. **Document specific descriptors** needed for Purdue's use cases +3. **Design UI mockups** for descriptor-based filtering +4. **Create proof-of-concept** once API is available +5. **Build pilot keys** using the same descriptor data +6. **Test integrated browsing + identification workflow** with users + +## Resources + +- TaxonWorks Matrices Documentation: https://docs.taxonworks.org/guide/Manual/matrices.html +- TaxonWorks Keys Documentation: https://docs.taxonworks.org/guide/Manual/Keys/ +- TaxonWorks API: https://api.taxonworks.org/ +- TaxonWorks Glossary: https://docs.taxonworks.org/about/glossary.html +- Project tokens are not secrets in this system (data is open) \ No newline at end of file