-
Notifications
You must be signed in to change notification settings - Fork 3
/
readme.html
335 lines (275 loc) · 13.5 KB
/
readme.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>mopy readme</title>
<meta name="generator" content="TextMate http://macromates.com/">
<meta name="author" content="Chris Sutton">
<style type="text/css">
pre { color: #FFFFFF; background-color: #303E51; padding:5px; border: 1px solid #cccbba;}
body { background-color: #EFFCFD;}
h2 { padding-top: 3em; }
</style>
<!-- Date: 2007-09-20 -->
</head>
<body>
<h1 id="mopyreadme">Mopy Readme</h1>
<h2 id="contents">Contents</h2>
<ol>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#interactivesessionexamplea.k.a.whyusemopy">Interactive Session Example (a.k.a. “why use <code>mopy</code> ?”)</a></li>
<li><a href="#requirements">Requirements</a></li>
<li><a href="#installation">Installation</a></li>
<li><a href="#mopyclasses">Mopy classes</a></li>
<li><a href="#mopyproperties">Mopy properties</a></li>
<li><a href="#examplesofmopyinuse">Examples of mopy in use</a></li>
<li><a href="#developers">Developers</a></li>
</ol>
<h2 id="introduction">Introduction</h2>
<p><code>mopy</code> is the Music Ontology Python library, designed to provide easy to use python bindings for Music Ontology terms for the creation and manipulation of Music Ontology data. <code>mopy</code> includes :</p>
<ul>
<li>All terms from :
<ul>
<li>the <a href="http://www.musicontology.com/">Music Ontology</a></li>
<li>the <a href="http://www.foaf-project.org/">Friend of a Friend</a> (FOAF) ontology</li>
<li>the <a href="http://moustaki.org/c4dm/timeline.owl">Timeline</a> ontology</li>
<li>the (new !) <a href="http://purl.org/ontology/chord/">Chord Ontology</a></li>
</ul></li>
<li>Easy conversion between RDF data and mopy objects
<ul>
<li>RDF can be read/written in XML or N3 format</li>
</ul></li>
<li>Type checking based on ontology definitions, to aid correct usage of ontology terms</li>
</ul>
<h2 id="interactivesessionexamplea.k.a.whyusemopy">Interactive Session Example (a.k.a. “why use <code>mopy</code> ?”)</h2>
<p>Using rdflib directly, somebody might try to write about their friend who’s in a band as follows :</p>
<pre><code>Python 2.4.4 (#1, Oct 18 2006, 10:34:39)
[GCC 4.0.1 (Apple Computer, Inc. build 5341)] on darwin
>>> import rdflib
>>> from rdflib import URIRef, Literal, BNode, RDF, RDFS, Namespace
>>> g = rdflib.ConjunctiveGraph()
>>> me = URIRef("http://mydomain.org/me")
>>> FOAF_ns = Namespace("http://xmlns.com/foaf/0.1/")
>>> g.add((me, RDF.type, FOAF_ns["Person"]))
>>> g.add((me, FOAF_ns["name"], Literal("Joe Bloggs")))
>>> artist = URIRef("http://zeitgeist.com/music/artist/FIXME")
>>> MO_ns = Namespace("http://purl.org/ontology/mo/")
>>> g.add((artist, RDF.type, MO_ns["music_artist"]))
>>> g.add((artist, FOAF_ns["nam"], Literal("Superstar artist")))
>>> g.add((me, FOAF_ns["interest"], artist))
>>> g.add((me, FOAF_ns["knows"], artist))
</code></pre>
<p>This can get quite tedious. Plus, there are mistakes (typo “name” property to “nam”, they meant mo:SoloMusicArtist rather than mo:music_artist, and foaf:interest is intended to link to a page about a topic of interest, not the topic itself) and it’s not easy to fix mistakes. For example, if the user needs to change the URI of the artist, they’ll have to write a loop to update all triples of relevance.</p>
<p>Here’s the equivalent session using <code>mopy</code> :</p>
<pre><code>[GCC 4.0.1 (Apple Computer, Inc. build 5341)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import mopy
>>> me = mopy.foaf.Person("http://mydomain.org/me")
>>> me.name = "Joe Bloggs"
>>> artist = mopy.mo.music_artist("http://zeitgeist.com/music/artist/FIXME")
AttributeError: 'module' object has no attribute 'music_artist'
>>> dir(mopy.mo)
['AnalogSignal', 'Arrangement', 'Arranger', 'AudioFile', 'CD', 'Composer', 'Composition', 'Conductor',
'CorporateBody', 'DAT', 'DCC', 'DVDA', 'DigitalSignal', 'ED2K', 'Festival', 'Genre', 'Instrument',
'Instrumentation', 'Label', 'Libretto', 'Listener', 'Lyrics', 'MD', 'MagneticTape', 'Medium', 'Movement',
'MusicArtist', 'MusicGroup', 'MusicalExpression', 'MusicalItem', 'MusicalManifestation', 'MusicalWork',
'Orchestration', 'Performance', 'Performer', 'PublishedLibretto', 'PublishedLyrics', 'PublishedScore', 'Record',
'Recording', 'ReleaseStatus', 'ReleaseType', 'SACD', 'Score', 'Show', 'Signal', 'SoloMusicArtist', 'Sound',
'SoundEngineer', 'Stream', 'Torrent', 'Track', 'Vinyl', '__builtins__', '__doc__', '__file__', '__name__',
'__path__', 'album', 'audiobook', 'bootleg', 'compilation', 'ep', 'interview', 'live', 'mopy', 'official',
'promotion', 'remix', 'soundtrack', 'spokenword']
>>> artist = mopy.mo.SoloMusicArtist("http://zeitgeist.com/music/artist/FIXME")
>>> artist.nam = "Superstar Artist"
AttributeError: Not allowed add new attributes to classes ! Typo ?
>>> artist.name = "Superstar Artist"
>>> me.interest = artist
TypeError: Invalid type ! Got <class 'mopy.model.mo___MusicArtist'> but expected one of : <class 'mopy.model.foaf___Document'>
>>> help (mopy.foaf.Person.interest)
Help on property:
A page about a topic of interest to this person.
>>> me.knows = artist
</code></pre>
<p>The user has avoided the mistakes which are so easy to make dealing directly with triples, and they can then update the artist’s URI as easily as :</p>
<pre><code>>>> artist.URI = "http://zitgist.com/music/artist/62b86b55-e0aa-446f-b326-054576968310"
</code></pre>
<h2 id="requirements">Requirements</h2>
<ul>
<li>Written and tested on python 2.4 but may work fine on 2.3 or 2.5 - let us know if you try :)</li>
<li>Python libraries :
<ul>
<li><a href="http://rdflib.org/">rdflib</a> v2.4.0 (easy_install)</li>
</ul></li>
</ul>
<h2 id="installation">Installation</h2>
<p>To install mopy, either check out the motools project from SVN and run mopy/genpy.py to generate mopy’s package files, or download the mopy package directly from <a href="http://sourceforge.net/project/showfiles.php?group_id=202492">sourceforge</a>. For now, just copy the mopy directory into your working directory, or your python’s library directory, we’ll be releasing an easier-to-install package soon :)</p>
<h2 id="mopyclasses"><code>mopy</code> Classes</h2>
<p>Start by importing the mopy package :</p>
<pre><code>>>> import mopy
</code></pre>
<p>Terms and instances are organised by namespace :</p>
<pre><code>>>> dir(mopy)
['MusicInfo', 'PropertySet', 'RDFInterface', '__builtins__', '__doc__', '__file__', '__name__',
'__path__', 'chord', 'event', 'exportRDFFile', 'exportRDFGraph', 'foaf', 'frbr', 'geo', 'importRDFFile',
'importRDFGraph', 'key', 'mo', 'model', 'owl', 'rdfs', 'time', 'timeline', 'tzont']
>>> dir(mopy.key)
['Key', 'Note', '__builtins__', '__doc__', '__file__', '__name__', '__path__', 'mopy']
</code></pre>
<p>And you can pull terms from a particular ontology as you’d expect :</p>
<pre><code>>>> from mopy.mo import MusicArtist, Record, Performance
</code></pre>
<p>To check what properties an object can take, use dir :</p>
<pre><code>>>> dir(mopy.mo.MusicArtist)
</code></pre>
<p>Constructors take the URI of the resource, or if omitted, act as blank nodes :</p>
<pre><code>>>> band1 = mopy.mo.MusicGroup()
>>> print band1
-- MusicGroup --
>>> band2 = mopy.mo.MusicGroup("http://band2.com/us")
>>> print band2
-- MusicGroup @ http://band2.com/us --
</code></pre>
<h2 id="mopyproperties"><code>mopy</code> Properties</h2>
<p>Properties are all treated as sets (so have no ordering), but we provide the shortcut of the ‘=’ operator to assign a one element set :</p>
<pre><code>>>> band1.name = "awesome band"
>>> band1.name.add("DEATH MONKEYS")
>>> print band1
-- MusicGroup --
name : DEATH MONKEYS
name : awesome band
>>> member_names = ["Baz", "Bill", "Bob", "Clifton"]
>>> for m in member_names:
... member = mopy.mo.SoloMusicArtist()
... member.name = m
... band1.member.add(member)
...
>>> print band1
-- MusicGroup --
member : <class 'mopy.model.mo___SoloMusicArtist'>
member : <class 'mopy.model.mo___SoloMusicArtist'>
member : <class 'mopy.model.mo___SoloMusicArtist'>
member : <class 'mopy.model.mo___SoloMusicArtist'>
name : DEATH MONKEYS
name : awesome band
>>> print "\n".join(str(x) for x in band1.member)
-- SoloMusicArtist --
name : Baz
-- SoloMusicArtist --
name : Bill
-- SoloMusicArtist --
name : Bob
-- SoloMusicArtist --
name : Clifton
</code></pre>
<h2 id="musicinfoobjects"><code>MusicInfo</code> objects</h2>
<p>To bundle up multiple mopy objects for serialisation, you can use the <code>MusicInfo</code> class :</p>
<pre><code>>>> mi = mopy.MusicInfo([band1] + list(band1.member))
>>> for o in mi.MusicGroupIdx.values():
... print o
-- MusicGroup @ http://band1.com/us --
member : <class 'mopy.model.mo___SoloMusicArtist'> @ blind:5429B6CE9A4F5096
member : <class 'mopy.model.mo___SoloMusicArtist'> @ blind:7EA44980E55B36F6
member : <class 'mopy.model.mo___SoloMusicArtist'> @ blind:367299F35DFDD780
member : <class 'mopy.model.mo___SoloMusicArtist'> @ blind:47FF277BE93C35CD
name : DEATH MONKEYS
name : awesome band
>>> for o in mi.SoloMusicArtistIdx.values():
... print o
-- SoloMusicArtist @ blind:7EA44980E55B36F6 --
name : Bill
-- SoloMusicArtist @ blind:367299F35DFDD780 --
name : Bob
-- SoloMusicArtist @ blind:5429B6CE9A4F5096 --
name : Baz
-- SoloMusicArtist @ blind:47FF277BE93C35CD --
name : Clifton
</code></pre>
<p>Two python objects with the same URI will become a single python object within the MusicInfo object :</p>
<pre><code>>>> mi2 = mopy.MusicInfo()
>>> a1 = mopy.mo.MusicArtist("http://example.org/x")
>>> a1.name = "Martin"
>>> a2 = mopy.mo.MusicArtist("http://example.org/x")
>>> a2.name = "Martin Jones"
>>> mi2.add(a1)
>>> mi2.add(a2)
>>> for o in mi2.MainIdx.values():
... print o
-- MusicArtist @ http://example.org/x --
name : Martin Jones
name : Martin
</code></pre>
<p>The functions in mopy.RDFInterface allow for creation of MusicInfo objects by reading in RDF, and the serialisation of MusicInfo objects as RDF (in XML or N3 format).
eg.</p>
<pre><code>>>> mopy.RDFInterface.exportRDFFile(mi, "greatband.rdf", "n3")
</code></pre>
<p>produces:</p>
<pre><code>@prefix _25: <http://band1.com/>.
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
@prefix mo: <http://purl.org/ontology/mo/>.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
_25:us a mo:MusicGroup;
foaf:member [ a mo:SoloMusicArtist;
foaf:name "Bob"],
[ a mo:SoloMusicArtist;
foaf:name "Clifton"],
[ a mo:SoloMusicArtist;
foaf:name "Bill"],
[ a mo:SoloMusicArtist;
foaf:name "Baz"];
foaf:name "DEATH MONKEYS",
"awesome band".
</code></pre>
<h2 id="examplesofmopyinuse">Examples of <code>mopy</code> in use</h2>
<ul>
<li>The <a href="http://sourceforge.net/projects/motools/"><code>gnat</code> project</a> is using <code>mopy</code> to store information about a user’s music collection.</li>
</ul>
<p>eg. for metadata lookup : (from <code>AudioCollection.py</code>)</p>
<pre><code>lookup = MbzTrackLookup(filename)
mbzuri = lookup.getMbzTrackURI()
mbzconvert = MbzURIConverter(mbzuri)
af = AudioFile(urlencode(os.path.basename(filename)))
mbz = Track(mbzconvert.getURI())
mbz.available_as = af
mi.add(af); mi.add(mbz)
</code></pre>
<ul>
<li><p>A more detailed use can be found in the FPTrackLookup.py fingerprinting file.</p></li>
<li><p>Some Chord Ontology <a href="http://sourceforge.net/projects/motools/">convertor tools</a> are using mopy’s timeline and chord ontology support to convert existing transcription formats to RDF.</p></li>
</ul>
<p>eg. from <code>labchords2RDF.py</code> :</p>
<pre><code>tl = RelativeTimeLine("#tl")
tl.label = "Timeline derived from "+infilename
tl.maker = program
mi.add(tl)
intervalNum = 0
for line in lines:
i = Interval("#i"+str(intervalNum))
try:
[start_s, end_s, label] = parseLabLine(line)
i.beginsAtDuration = secondsToXSDDuration(start_s)
i.endsAtDuration = secondsToXSDDuration(end_s)
i.label = "Interval containing "+label+" chord."
i.onTimeLine = tl
# Produce chord object for the label :
chordURI = "http://purl.org/ontology/chord/symbol/"+label.replace("#","s")
c = mopy.chord.Chord(chordURI)
c_event = mopy.chord.ChordEvent("#ce"+str(intervalNum))
c_event.chord = c
c_event.time = i
except Exception, e:
raise Exception("Problem parsing input file at line "+str(intervalNum+1)+" !\n"+str(e))
mi.add(i)
mi.add(c)
mi.add(c_event)
intervalNum+=1
</code></pre>
<ul>
<li>The <a href="http://sourceforge.net/projects/mypyspace/">MyPySpace</a> project is using <code>mopy</code> to model FOAF relationships between MySpace users.</li>
</ul>
<h2 id="developers">Developers</h2>
<ul>
<li>Christopher Sutton : <code>chris (at) chrissutton (dot) org</code> </li>
<li>Yves Raimond : <code>yves (at) dbtune (dot) org</code> </li>
</ul>
</body>
</html>