idtap 0.1.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- idtap-0.1.5/CLAUDE.md +110 -0
- idtap-0.1.5/LICENSE +21 -0
- idtap-0.1.5/MANIFEST.in +11 -0
- idtap-0.1.5/PKG-INFO +383 -0
- idtap-0.1.5/README.md +337 -0
- idtap-0.1.5/SECURITY.md +219 -0
- idtap-0.1.5/idtap/__init__.py +70 -0
- idtap-0.1.5/idtap/audio_models.py +247 -0
- idtap-0.1.5/idtap/auth.py +206 -0
- idtap-0.1.5/idtap/classes/__init__.py +0 -0
- idtap-0.1.5/idtap/classes/articulation.py +63 -0
- idtap-0.1.5/idtap/classes/assemblage.py +156 -0
- idtap-0.1.5/idtap/classes/automation.py +164 -0
- idtap-0.1.5/idtap/classes/chikari.py +53 -0
- idtap-0.1.5/idtap/classes/group.py +77 -0
- idtap-0.1.5/idtap/classes/meter.py +279 -0
- idtap-0.1.5/idtap/classes/note_view_phrase.py +14 -0
- idtap-0.1.5/idtap/classes/phrase.py +455 -0
- idtap-0.1.5/idtap/classes/piece.py +1207 -0
- idtap-0.1.5/idtap/classes/pitch.py +365 -0
- idtap-0.1.5/idtap/classes/raga.py +340 -0
- idtap-0.1.5/idtap/classes/section.py +84 -0
- idtap-0.1.5/idtap/classes/trajectory.py +675 -0
- idtap-0.1.5/idtap/client.py +716 -0
- idtap-0.1.5/idtap/enums.py +6 -0
- idtap-0.1.5/idtap/py.typed +2 -0
- idtap-0.1.5/idtap/secure_storage.py +342 -0
- idtap-0.1.5/idtap/tests/articulation_test.py +64 -0
- idtap-0.1.5/idtap/tests/assemblage_test.py +156 -0
- idtap-0.1.5/idtap/tests/auth_logout_test.py +166 -0
- idtap-0.1.5/idtap/tests/auth_test.py +47 -0
- idtap-0.1.5/idtap/tests/automation_test.py +167 -0
- idtap-0.1.5/idtap/tests/chikari_test.py +16 -0
- idtap-0.1.5/idtap/tests/client_test.py +45 -0
- idtap-0.1.5/idtap/tests/group_test.py +199 -0
- idtap-0.1.5/idtap/tests/meter_test.py +159 -0
- idtap-0.1.5/idtap/tests/note_view_phrase_test.py +17 -0
- idtap-0.1.5/idtap/tests/phrase_test.py +353 -0
- idtap-0.1.5/idtap/tests/piece_test.py +908 -0
- idtap-0.1.5/idtap/tests/pitch_test.py +554 -0
- idtap-0.1.5/idtap/tests/raga_test.py +545 -0
- idtap-0.1.5/idtap/tests/section_test.py +34 -0
- idtap-0.1.5/idtap/tests/trajectory_test.py +425 -0
- idtap-0.1.5/idtap/utils.py +49 -0
- idtap-0.1.5/idtap.egg-info/PKG-INFO +383 -0
- idtap-0.1.5/idtap.egg-info/SOURCES.txt +50 -0
- idtap-0.1.5/idtap.egg-info/dependency_links.txt +1 -0
- idtap-0.1.5/idtap.egg-info/requires.txt +19 -0
- idtap-0.1.5/idtap.egg-info/top_level.txt +1 -0
- idtap-0.1.5/pyproject.toml +109 -0
- idtap-0.1.5/requirements.txt +12 -0
- idtap-0.1.5/setup.cfg +4 -0
idtap-0.1.5/CLAUDE.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# IDTAP Python API Development Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
The Python API (`idtap_api`) is a sophisticated client library for interacting with the IDTAP (Interactive Digital Transcription and Analysis Platform) server, specifically designed for transcribing, analyzing, and managing Hindustani music recordings.
|
|
5
|
+
|
|
6
|
+
## Key Development Points
|
|
7
|
+
|
|
8
|
+
### Dependencies Management
|
|
9
|
+
- **Keep `Pipfile` and `pyproject.toml` in sync** - this is critical!
|
|
10
|
+
- Add new packages: `pipenv install package-name`
|
|
11
|
+
- Then manually add to `pyproject.toml` dependencies array
|
|
12
|
+
- Core deps: requests, pyhumps, keyring, cryptography, PyJWT, pymongo, google-auth-oauthlib
|
|
13
|
+
|
|
14
|
+
### Testing
|
|
15
|
+
- **Unit tests**: `pytest python/idtap_api/tests/` (uses `responses` for HTTP mocking)
|
|
16
|
+
- **Integration tests**: `python python/api_testing/api_test.py` (requires live server auth)
|
|
17
|
+
- Test structure: Complete coverage of data models, client functionality, and authentication
|
|
18
|
+
|
|
19
|
+
### Build/Package/Publish
|
|
20
|
+
```bash
|
|
21
|
+
python -m build
|
|
22
|
+
python -m twine upload dist/* # or --repository testpypi for testing
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Architecture
|
|
26
|
+
|
|
27
|
+
### Main Components
|
|
28
|
+
- **`SwaraClient`** (`client.py`) - Main HTTP client with OAuth authentication
|
|
29
|
+
- **Data Models** (`/classes/`) - Rich musical transcription classes (Piece, Phrase, Trajectory, etc.)
|
|
30
|
+
- **Authentication** (`auth.py` + `secure_storage.py`) - OAuth flow with secure token storage
|
|
31
|
+
- **Utils** (`utils.py`) - camelCase ↔ snake_case conversion
|
|
32
|
+
|
|
33
|
+
### Key Classes
|
|
34
|
+
- **`Piece`**: Central transcription container with multi-track support, sections, audio association
|
|
35
|
+
- **`SwaraClient`**: API interface with methods for transcription CRUD, audio download, permissions
|
|
36
|
+
- **Musical Elements**: Phrase, Trajectory, Pitch, Raga, Section, Meter, Articulation
|
|
37
|
+
|
|
38
|
+
### Security/Authentication
|
|
39
|
+
- **OAuth Flow**: Server-based OAuth (not direct Google) → local HTTP server → secure storage
|
|
40
|
+
- **Storage Layers**: OS Keyring (primary) → AES-256 encrypted file (fallback) → plaintext (legacy)
|
|
41
|
+
- **CSRF Protection**: State parameter validation
|
|
42
|
+
- **Permissions**: User-based access control with public/private visibility
|
|
43
|
+
|
|
44
|
+
## Development Patterns
|
|
45
|
+
|
|
46
|
+
### Code Conventions
|
|
47
|
+
- **snake_case** for Python code
|
|
48
|
+
- **camelCase ↔ snake_case** conversion via `pyhumps` for API communication
|
|
49
|
+
- **Type hints** throughout
|
|
50
|
+
- **Backwards compatibility** maintained (especially token storage migration)
|
|
51
|
+
|
|
52
|
+
### Serialization Pattern
|
|
53
|
+
```python
|
|
54
|
+
class DataModel:
|
|
55
|
+
def to_json(self) -> Dict[str, Any]:
|
|
56
|
+
# Convert to dict with camelCase keys for API
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def from_json(obj: Dict[str, Any]) -> 'DataModel':
|
|
60
|
+
# Parse from API response with snake_case conversion
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Package Structure
|
|
64
|
+
```
|
|
65
|
+
python/idtap_api/
|
|
66
|
+
├── __init__.py # Public API exports
|
|
67
|
+
├── client.py # HTTP client (SwaraClient)
|
|
68
|
+
├── auth.py # OAuth authentication
|
|
69
|
+
├── secure_storage.py # Token security layers
|
|
70
|
+
├── enums.py # Instrument types, etc.
|
|
71
|
+
├── utils.py # camelCase conversion utilities
|
|
72
|
+
├── classes/ # Musical data models
|
|
73
|
+
└── tests/ # Unit tests
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## API Endpoints (via SwaraClient)
|
|
77
|
+
- **Transcriptions**: GET/POST `/api/transcription/{id}`, GET `/api/transcriptions`
|
|
78
|
+
- **Data Export**: GET `/api/transcription/{id}/json`, `/api/transcription/{id}/excel`
|
|
79
|
+
- **Audio**: GET `/audio/{format}/{id}.{format}`
|
|
80
|
+
- **Permissions**: POST `/api/visibility`
|
|
81
|
+
- **OAuth**: GET `/oauth/authorize`, POST `/oauth/token`
|
|
82
|
+
|
|
83
|
+
## Musical Domain Knowledge
|
|
84
|
+
- **Hindustani Music Focus**: Transcription system for Indian classical music
|
|
85
|
+
- **Complex Data Models**: Supports microtonal pitches, ragas, articulations, meter cycles
|
|
86
|
+
- **Multi-instrument**: Sitar, Vocal (Male/Female) with instrument-specific features
|
|
87
|
+
- **Analytical Tools**: Trajectory categorization, phrase grouping, temporal analysis
|
|
88
|
+
|
|
89
|
+
## Development Workflow
|
|
90
|
+
1. **Data Model Development**: Create/modify classes in `/classes/` with proper serialization
|
|
91
|
+
2. **Client Method Development**: Add HTTP methods in `client.py` with authentication
|
|
92
|
+
3. **Testing**: Write unit tests (mocked) + integration tests (live API)
|
|
93
|
+
4. **Sync Dependencies**: Update both `Pipfile` and `pyproject.toml`
|
|
94
|
+
5. **Build/Test/Publish**: Use standard Python packaging tools
|
|
95
|
+
|
|
96
|
+
## Installation Commands
|
|
97
|
+
```bash
|
|
98
|
+
# Development
|
|
99
|
+
pip install -e python/
|
|
100
|
+
pipenv install --dev
|
|
101
|
+
|
|
102
|
+
# Testing
|
|
103
|
+
pytest python/idtap_api/tests/
|
|
104
|
+
python python/api_testing/api_test.py
|
|
105
|
+
|
|
106
|
+
# Package management
|
|
107
|
+
pipenv install package-name # then manually add to pyproject.toml
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
This API provides a production-ready foundation for complex musical transcription analysis with modern security practices and comprehensive testing coverage.
|
idtap-0.1.5/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Jon Myers
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
idtap-0.1.5/MANIFEST.in
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Include important files in source distribution
|
|
2
|
+
include README.md
|
|
3
|
+
include LICENSE
|
|
4
|
+
include SECURITY.md
|
|
5
|
+
include CLAUDE.md
|
|
6
|
+
include requirements.txt
|
|
7
|
+
recursive-include idtap *.py
|
|
8
|
+
recursive-include idtap *.typed
|
|
9
|
+
recursive-exclude * __pycache__
|
|
10
|
+
recursive-exclude * *.py[co]
|
|
11
|
+
exclude idtap.egg-info
|
idtap-0.1.5/PKG-INFO
ADDED
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: idtap
|
|
3
|
+
Version: 0.1.5
|
|
4
|
+
Summary: Python client library for IDTAP - Interactive Digital Transcription and Analysis Platform for Hindustani music
|
|
5
|
+
Author-email: Jon Myers <jon@swara.studio>
|
|
6
|
+
Maintainer-email: Jon Myers <jon@swara.studio>
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://swara.studio
|
|
9
|
+
Project-URL: Documentation, https://github.com/UCSC-IDTAP/Python-API
|
|
10
|
+
Project-URL: Repository, https://github.com/UCSC-IDTAP/Python-API
|
|
11
|
+
Project-URL: Bug Tracker, https://github.com/UCSC-IDTAP/Python-API/issues
|
|
12
|
+
Keywords: music,transcription,hindustani,indian-classical,musicology,ethnomusicology,raga,pitch-analysis,audio-analysis
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
20
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Operating System :: OS Independent
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: requests>=2.31.0
|
|
29
|
+
Requires-Dist: requests-toolbelt>=1.0.0
|
|
30
|
+
Requires-Dist: pyhumps>=3.8.0
|
|
31
|
+
Requires-Dist: keyring>=24.0.0
|
|
32
|
+
Requires-Dist: cryptography>=41.0.0
|
|
33
|
+
Requires-Dist: PyJWT>=2.8.0
|
|
34
|
+
Requires-Dist: google-auth-oauthlib>=1.0.0
|
|
35
|
+
Requires-Dist: pymongo>=4.0.0
|
|
36
|
+
Provides-Extra: dev
|
|
37
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
38
|
+
Requires-Dist: responses>=0.23.0; extra == "dev"
|
|
39
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
40
|
+
Requires-Dist: isort>=5.12.0; extra == "dev"
|
|
41
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
42
|
+
Requires-Dist: flake8>=6.0.0; extra == "dev"
|
|
43
|
+
Provides-Extra: linux
|
|
44
|
+
Requires-Dist: secretstorage>=3.3.0; extra == "linux"
|
|
45
|
+
Dynamic: license-file
|
|
46
|
+
|
|
47
|
+
# IDTAP Python API
|
|
48
|
+
|
|
49
|
+
[](https://badge.fury.io/py/idtap-api)
|
|
50
|
+
[](https://idtap-python-api.readthedocs.io/en/latest/?badge=latest)
|
|
51
|
+
[](https://www.python.org/downloads/)
|
|
52
|
+
[](https://opensource.org/licenses/MIT)
|
|
53
|
+
|
|
54
|
+
Python client library for **IDTAP** (Interactive Digital Transcription and Analysis Platform) - a web-based research platform developed at UC Santa Cruz for transcribing, analyzing, and archiving Hindustani (North Indian classical) music recordings using trajectory-based notation designed specifically for oral melodic traditions.
|
|
55
|
+
|
|
56
|
+
## About IDTAP
|
|
57
|
+
|
|
58
|
+
IDTAP represents a paradigm shift in musical transcription and analysis. Rather than forcing oral traditions into Western notational frameworks, it uses **trajectories** as the fundamental musical unit—archetypal paths between pitches that capture the continuous melodic movement central to Hindustani music.
|
|
59
|
+
|
|
60
|
+
**Key Innovation**: Instead of discrete notes, IDTAP models music through:
|
|
61
|
+
- **Trajectory-based notation** - Continuous pitch contours rather than fixed notes
|
|
62
|
+
- **Microtonal precision** - Cent-based tuning with flexible raga systems
|
|
63
|
+
- **Idiomatic articulations** - Performance techniques specific to each instrument
|
|
64
|
+
- **Hierarchical segmentation** - Phrases, sections, and formal structures
|
|
65
|
+
|
|
66
|
+
## Features
|
|
67
|
+
|
|
68
|
+
- **Trajectory-Based Data Access** - Load and analyze transcriptions using the trajectory notation system
|
|
69
|
+
- **Hindustani Music Analysis** - Work with raga-aware transcriptions and microtonal pitch data
|
|
70
|
+
- **Audio Download** - Retrieve associated audio recordings in multiple formats
|
|
71
|
+
- **Secure Authentication** - OAuth integration with encrypted token storage
|
|
72
|
+
|
|
73
|
+
## Installation
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pip install idtap-api
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Optional Dependencies
|
|
80
|
+
|
|
81
|
+
For enhanced Linux keyring support:
|
|
82
|
+
```bash
|
|
83
|
+
pip install idtap-api[linux]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
For development:
|
|
87
|
+
```bash
|
|
88
|
+
pip install idtap-api[dev]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Quick Start
|
|
92
|
+
|
|
93
|
+
### Authentication & Basic Usage
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from idtap_api import SwaraClient, Piece, Instrument
|
|
97
|
+
|
|
98
|
+
# Initialize client - connects to swara.studio platform
|
|
99
|
+
client = SwaraClient() # Automatic OAuth via Google
|
|
100
|
+
|
|
101
|
+
# Browse available transcriptions
|
|
102
|
+
transcriptions = client.get_viewable_transcriptions()
|
|
103
|
+
print(f"Found {len(transcriptions)} transcriptions")
|
|
104
|
+
|
|
105
|
+
# Load a Hindustani music transcription
|
|
106
|
+
piece_data = client.get_piece("transcription-id")
|
|
107
|
+
piece = Piece.from_json(piece_data)
|
|
108
|
+
|
|
109
|
+
print(f"Transcription: {piece.title}")
|
|
110
|
+
print(f"Raga: {piece.raga.name if piece.raga else 'Unknown'}")
|
|
111
|
+
print(f"Instrument: {piece.instrumentation}")
|
|
112
|
+
print(f"Trajectories: {sum(len(p.trajectories) for p in piece.phrases)}")
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Working with Trajectory-Based Transcriptions
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
# Analyze trajectory-based musical structure
|
|
119
|
+
for phrase in piece.phrases:
|
|
120
|
+
print(f"Phrase {phrase.phrase_number}: {len(phrase.trajectories)} trajectories")
|
|
121
|
+
|
|
122
|
+
# Examine individual trajectories (fundamental units of IDTAP)
|
|
123
|
+
for traj in phrase.trajectories:
|
|
124
|
+
if traj.pitch_array:
|
|
125
|
+
# Each trajectory contains continuous pitch movement
|
|
126
|
+
start_pitch = traj.pitch_array[0].pitch_number
|
|
127
|
+
end_pitch = traj.pitch_array[-1].pitch_number
|
|
128
|
+
print(f" Trajectory {traj.traj_number}: {start_pitch:.2f} → {end_pitch:.2f}")
|
|
129
|
+
|
|
130
|
+
# Check for articulations (performance techniques)
|
|
131
|
+
if traj.articulation:
|
|
132
|
+
techniques = [art.stroke for art in traj.articulation if art.stroke]
|
|
133
|
+
print(f" Articulations: {', '.join(techniques)}")
|
|
134
|
+
|
|
135
|
+
# Raga analysis (theoretical framework)
|
|
136
|
+
if piece.raga:
|
|
137
|
+
print(f"Raga: {piece.raga.name}")
|
|
138
|
+
if hasattr(piece.raga, 'aroha') and piece.raga.aroha:
|
|
139
|
+
print(f"Aroha (ascending): {piece.raga.aroha}")
|
|
140
|
+
if hasattr(piece.raga, 'avaroha') and piece.raga.avaroha:
|
|
141
|
+
print(f"Avaroha (descending): {piece.raga.avaroha}")
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Audio Handling
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
# Download audio in different formats
|
|
148
|
+
audio_bytes = client.download_audio("audio-id", format="wav")
|
|
149
|
+
with open("recording.wav", "wb") as f:
|
|
150
|
+
f.write(audio_bytes)
|
|
151
|
+
|
|
152
|
+
# Download all audio associated with a transcription
|
|
153
|
+
client.download_and_save_transcription_audio(piece, directory="./audio/")
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Data Export
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
# Export transcription data
|
|
160
|
+
excel_data = client.excel_data(piece_id)
|
|
161
|
+
with open("analysis.xlsx", "wb") as f:
|
|
162
|
+
f.write(excel_data)
|
|
163
|
+
|
|
164
|
+
json_data = client.json_data(piece_id)
|
|
165
|
+
with open("transcription.json", "wb") as f:
|
|
166
|
+
f.write(json_data)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Working with Hindustani Music Data
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
from idtap_api import Piece, Phrase, Trajectory, Pitch, Raga, Instrument
|
|
173
|
+
|
|
174
|
+
# Example: Analyze a sitar transcription
|
|
175
|
+
sitar_pieces = [t for t in transcriptions if t.get('instrumentation') == 'Sitar']
|
|
176
|
+
|
|
177
|
+
for trans_meta in sitar_pieces[:3]: # First 3 sitar pieces
|
|
178
|
+
piece = Piece.from_json(client.get_piece(trans_meta['_id']))
|
|
179
|
+
|
|
180
|
+
# Count different types of trajectories (IDTAP's innovation)
|
|
181
|
+
trajectory_types = {}
|
|
182
|
+
for phrase in piece.phrases:
|
|
183
|
+
for traj in phrase.trajectories:
|
|
184
|
+
traj_type = getattr(traj, 'curve_type', 'straight')
|
|
185
|
+
trajectory_types[traj_type] = trajectory_types.get(traj_type, 0) + 1
|
|
186
|
+
|
|
187
|
+
print(f"{piece.title}:")
|
|
188
|
+
print(f" Raga: {piece.raga.name if piece.raga else 'Unknown'}")
|
|
189
|
+
print(f" Trajectory types: {trajectory_types}")
|
|
190
|
+
|
|
191
|
+
# Analyze articulation patterns (performance techniques)
|
|
192
|
+
articulations = []
|
|
193
|
+
for phrase in piece.phrases:
|
|
194
|
+
for traj in phrase.trajectories:
|
|
195
|
+
if traj.articulation:
|
|
196
|
+
articulations.extend([art.stroke for art in traj.articulation])
|
|
197
|
+
|
|
198
|
+
unique_arts = list(set(articulations))
|
|
199
|
+
print(f" Articulations used: {', '.join(unique_arts[:5])}") # First 5
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Key Classes
|
|
203
|
+
|
|
204
|
+
### SwaraClient
|
|
205
|
+
The main HTTP client for interacting with the IDTAP server.
|
|
206
|
+
|
|
207
|
+
**Key Methods:**
|
|
208
|
+
- `get_viewable_transcriptions()` - List accessible transcriptions
|
|
209
|
+
- `get_piece(id)` - Load transcription data
|
|
210
|
+
- `save_piece(data)` - Save transcription
|
|
211
|
+
- `excel_data(id)` / `json_data(id)` - Export data
|
|
212
|
+
- `download_audio(id, format)` - Download audio files
|
|
213
|
+
- `get_waiver_text()` - Display the research waiver text that must be read
|
|
214
|
+
- `agree_to_waiver(i_agree=True)` - Accept research waiver (required for first-time users)
|
|
215
|
+
- `has_agreed_to_waiver()` - Check if waiver has been accepted
|
|
216
|
+
|
|
217
|
+
### Musical Data Models
|
|
218
|
+
|
|
219
|
+
- **`Piece`** - Central transcription container with metadata, audio association, and musical content
|
|
220
|
+
- **`Phrase`** - Musical phrase containing trajectory data and categorizations
|
|
221
|
+
- **`Trajectory`** - Detailed pitch movement data with timing and articulations
|
|
222
|
+
- **`Pitch`** - Individual pitch points with frequency and timing information
|
|
223
|
+
- **`Raga`** - Indian musical scale/mode definitions with theoretical rules
|
|
224
|
+
- **`Section`** - Large structural divisions (alap, composition, etc.)
|
|
225
|
+
- **`Meter`** - Rhythmic cycle and tempo information
|
|
226
|
+
- **`Articulation`** - Performance technique annotations (meend, andolan, etc.)
|
|
227
|
+
|
|
228
|
+
### Specialized Features
|
|
229
|
+
|
|
230
|
+
- **Microtonal Pitch System** - Precise cent-based pitch representation
|
|
231
|
+
- **Hindustani Music Theory** - Raga rules, sargam notation, gharana traditions
|
|
232
|
+
- **Performance Analysis** - Ornament detection, phrase categorization
|
|
233
|
+
- **Multi-Track Support** - Simultaneous transcription of melody and drone
|
|
234
|
+
|
|
235
|
+
## Authentication
|
|
236
|
+
|
|
237
|
+
The client uses OAuth 2.0 flow with Google authentication. On first use, it will:
|
|
238
|
+
|
|
239
|
+
1. Open a browser for Google OAuth login
|
|
240
|
+
2. Securely store the authentication token using:
|
|
241
|
+
- OS keyring (preferred)
|
|
242
|
+
- Encrypted local file (fallback)
|
|
243
|
+
- Plain text (legacy, discouraged)
|
|
244
|
+
|
|
245
|
+
### Research Waiver Requirement
|
|
246
|
+
|
|
247
|
+
**First-time users must agree to a research waiver** before accessing transcription data. If you haven't agreed yet, you'll see an error when trying to access transcriptions:
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
client = SwaraClient()
|
|
251
|
+
transcriptions = client.get_viewable_transcriptions() # Will raise RuntimeError
|
|
252
|
+
|
|
253
|
+
# First, read the waiver text
|
|
254
|
+
waiver_text = client.get_waiver_text()
|
|
255
|
+
print("Research Waiver:")
|
|
256
|
+
print(waiver_text)
|
|
257
|
+
|
|
258
|
+
# After reading, agree to the waiver
|
|
259
|
+
client.agree_to_waiver(i_agree=True)
|
|
260
|
+
transcriptions = client.get_viewable_transcriptions() # Now works
|
|
261
|
+
|
|
262
|
+
# Check waiver status
|
|
263
|
+
if client.has_agreed_to_waiver():
|
|
264
|
+
print("Waiver agreed - full access available")
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Manual Token Management
|
|
268
|
+
|
|
269
|
+
```python
|
|
270
|
+
# Initialize without auto-login
|
|
271
|
+
client = SwaraClient(auto_login=False)
|
|
272
|
+
|
|
273
|
+
# Login manually when needed
|
|
274
|
+
from idtap_api import login_google
|
|
275
|
+
login_google()
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Advanced Usage
|
|
279
|
+
|
|
280
|
+
### Batch Processing
|
|
281
|
+
|
|
282
|
+
```python
|
|
283
|
+
# Process multiple transcriptions
|
|
284
|
+
transcriptions = client.get_viewable_transcriptions()
|
|
285
|
+
|
|
286
|
+
for trans in transcriptions:
|
|
287
|
+
if trans.get('instrumentation') == 'Sitar':
|
|
288
|
+
piece = Piece.from_json(client.get_piece(trans['_id']))
|
|
289
|
+
|
|
290
|
+
# Analyze sitar-specific features
|
|
291
|
+
total_meends = sum(
|
|
292
|
+
len([art for art in traj.articulation if art.stroke == 'meend'])
|
|
293
|
+
for phrase in piece.phrases
|
|
294
|
+
for traj in phrase.trajectories
|
|
295
|
+
)
|
|
296
|
+
print(f"{piece.title}: {total_meends} meends")
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Research Applications
|
|
300
|
+
|
|
301
|
+
```python
|
|
302
|
+
# Raga analysis across corpus
|
|
303
|
+
raga_stats = {}
|
|
304
|
+
for trans in transcriptions:
|
|
305
|
+
piece = Piece.from_json(client.get_piece(trans['_id']))
|
|
306
|
+
if piece.raga:
|
|
307
|
+
raga_name = piece.raga.name
|
|
308
|
+
raga_stats[raga_name] = raga_stats.get(raga_name, 0) + 1
|
|
309
|
+
|
|
310
|
+
print("Raga distribution:", raga_stats)
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## Development
|
|
314
|
+
|
|
315
|
+
### Running Tests
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
# Unit tests
|
|
319
|
+
pytest idtap_api/tests/
|
|
320
|
+
|
|
321
|
+
# Integration tests (requires authentication)
|
|
322
|
+
python api_testing/api_test.py
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Contributing
|
|
326
|
+
|
|
327
|
+
1. Fork the repository
|
|
328
|
+
2. Create a feature branch
|
|
329
|
+
3. Add tests for new functionality
|
|
330
|
+
4. Ensure all tests pass
|
|
331
|
+
5. Submit a pull request
|
|
332
|
+
|
|
333
|
+
## Documentation
|
|
334
|
+
|
|
335
|
+
- **API Reference**: Full documentation of all classes and methods
|
|
336
|
+
- **Musical Concepts**: Guide to Hindustani music terminology and theory
|
|
337
|
+
- **Research Examples**: Academic use cases and analysis workflows
|
|
338
|
+
|
|
339
|
+
## Platform Access
|
|
340
|
+
|
|
341
|
+
- **IDTAP Web Platform**: [swara.studio](https://swara.studio)
|
|
342
|
+
- **Source Code**: [github.com/jon-myers/idtap](https://github.com/jon-myers/idtap)
|
|
343
|
+
- **Research Paper**: "Beyond Notation: A Digital Platform for Transcribing and Analyzing Oral Melodic Traditions" (ISMIR 2025)
|
|
344
|
+
|
|
345
|
+
## Documentation
|
|
346
|
+
|
|
347
|
+
📖 **Complete documentation is available at [idtap-python-api.readthedocs.io](https://idtap-python-api.readthedocs.io/)**
|
|
348
|
+
|
|
349
|
+
- **[Installation Guide](https://idtap-python-api.readthedocs.io/en/latest/installation.html)** - Detailed setup instructions
|
|
350
|
+
- **[Authentication](https://idtap-python-api.readthedocs.io/en/latest/authentication.html)** - OAuth setup and token management
|
|
351
|
+
- **[Quickstart Tutorial](https://idtap-python-api.readthedocs.io/en/latest/quickstart.html)** - Get started in minutes
|
|
352
|
+
- **[API Reference](https://idtap-python-api.readthedocs.io/en/latest/api/)** - Complete class and method documentation
|
|
353
|
+
- **[Examples](https://idtap-python-api.readthedocs.io/en/latest/examples/)** - Real-world usage examples
|
|
354
|
+
|
|
355
|
+
## Support
|
|
356
|
+
|
|
357
|
+
- **GitHub Issues**: [Report bugs and request features](https://github.com/UCSC-IDTAP/Python-API/issues)
|
|
358
|
+
- **Research Contact**: Jonathan Myers & Dard Neuman, UC Santa Cruz
|
|
359
|
+
- **Platform**: [swara.studio](https://swara.studio)
|
|
360
|
+
|
|
361
|
+
## License
|
|
362
|
+
|
|
363
|
+
MIT License - see LICENSE file for details.
|
|
364
|
+
|
|
365
|
+
## Citation
|
|
366
|
+
|
|
367
|
+
If you use IDTAP in academic research, please cite the ISMIR 2025 paper:
|
|
368
|
+
|
|
369
|
+
```bibtex
|
|
370
|
+
@inproceedings{myers2025beyond,
|
|
371
|
+
title={Beyond Notation: A Digital Platform for Transcribing and Analyzing Oral Melodic Traditions},
|
|
372
|
+
author={Myers, Jonathan and Neuman, Dard},
|
|
373
|
+
booktitle={Proceedings of the 26th International Society for Music Information Retrieval Conference},
|
|
374
|
+
pages={},
|
|
375
|
+
year={2025},
|
|
376
|
+
address={Daejeon, South Korea},
|
|
377
|
+
url={https://swara.studio}
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
**IDTAP** was developed at UC Santa Cruz with support from the National Endowment for the Humanities. The platform challenges Western-centric approaches to music representation by creating tools designed specifically for oral melodic traditions, enabling scholars to study Hindustani music on its own terms while applying cutting-edge computational methodologies.
|