mexico 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +22 -1
- data/VERSION +1 -1
- data/assets/fiesta/props/props.fst +13 -0
- data/info/releasenotes/0.0.11.md +17 -0
- data/lib/mexico/fiesta/interfaces/elan_interface.rb +358 -17
- data/lib/mexico/fiesta/interfaces/short_text_grid_interface.rb +59 -0
- data/lib/mexico/fiesta/interfaces/text_grid_interface.rb +72 -10
- data/lib/mexico/file_system/fiesta_document.rb +4 -0
- data/lib/mexico/file_system/head.rb +15 -0
- data/lib/mexico/file_system/interval_link.rb +5 -1
- data/lib/mexico/file_system/item.rb +5 -1
- data/lib/mexico/file_system/item_link.rb +5 -1
- data/lib/mexico/file_system/layer.rb +19 -1
- data/lib/mexico/file_system/layer_connector.rb +6 -1
- data/lib/mexico/file_system/layer_link.rb +5 -1
- data/lib/mexico/file_system/point_link.rb +5 -1
- data/lib/mexico/file_system/property.rb +15 -1
- data/lib/mexico/file_system/property_map.rb +38 -0
- data/lib/mexico/file_system/scale.rb +6 -1
- data/lib/mexico/file_system/section.rb +27 -1
- data/lib/mexico/util/fancy_writer.rb +47 -0
- data/lib/mexico/util.rb +5 -2
- data/spec/core/fancy_writer_spec.rb +77 -0
- data/spec/fiesta/elan_spec.rb +35 -2
- data/spec/fiesta/layer_prop_spec.rb +45 -0
- data/spec/fiesta/praat_spec.rb +19 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NTU2MmVjZDQ1ZGUyZjIyZTU2YWZjNzY5YzVmZGNhYmUzOTM0ZjE3Yw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
Zjc3NDE2NWUzMTM0ZTIwMzJiZDQ5ODQwMDQ0YWJiMDY5MDUzMzNiMQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ODNiZmI3N2JjMzY0ZjQ2YWQ3NGFiNTgwNTA1YzJiY2IxZDZkOTU4MGEzOWI1
|
10
|
+
MTllMjdjZTdiNGMzMGVmNTg4YWZjYmY4NGI2NTNlNDQ1NjRmNmI3YTcyNTMw
|
11
|
+
MWQ5ZDNjMzRkOWIwNmVjZWZkMWUzYTA4N2YyYWMzMDk0OGUzMzA=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZjRhODUzODVjMWY4YjlhMzNhZmRmYmZjYzU0ZTU4Nzc5NzNmZWU2ZTlkOThh
|
14
|
+
MzBkODNkZDU4M2RlNDNhNWI1YjUzNTdlMjMyZDc2MWJiZmZlYTZhNDQzOTg3
|
15
|
+
ZDk5NTUxNmQ4YmY4ZDRiMGUwYTIxYjZjYjliN2Q4NWU4M2FmZGM=
|
data/README.md
CHANGED
@@ -10,6 +10,27 @@ Its central organising unit is the **Corpus** class which allows researchers to
|
|
10
10
|
|
11
11
|
## Last Changes
|
12
12
|
|
13
|
+
## 0.0.11
|
14
|
+
|
15
|
+
Completed on March 24 2014.
|
16
|
+
|
17
|
+
+ [**#258**](http://intranet.sfb673.org/issues/258): Adds first working version of FancyWriter for creating formatted plain text file formats.
|
18
|
+
|
19
|
+
+ [**#154**](http://intranet.sfb673.org/issues/154): Adds export routine into the Praat ShortTextGrid format.
|
20
|
+
+ [**#155**](http://intranet.sfb673.org/issues/155): Adds TextGrid export functionality.
|
21
|
+
|
22
|
+
+ [**#156**](http://intranet.sfb673.org/issues/156): EAF export should now be complete, including metadata:
|
23
|
+
|
24
|
+
+ [**#234**](http://intranet.sfb673.org/issues/234): Spec test files are adopted to reflect additional ELAN features.
|
25
|
+
+ [**#248**](http://intranet.sfb673.org/issues/248): Layers now use property structures for additional configuration.
|
26
|
+
+ [**#251**](http://intranet.sfb673.org/issues/251): ELAN import now uses up-to-date method for adding layers.
|
27
|
+
+ [**#252**](http://intranet.sfb673.org/issues/252): Adds custom setter methods for identifiers in order to produce XML-valid IDs.
|
28
|
+
+ [**#253**](http://intranet.sfb673.org/issues/253): Fixes a bug where annotations with empty string values were skipped.
|
29
|
+
+ [**#255**](http://intranet.sfb673.org/issues/255): Persists the ANNOTATOR attribute from ELAN during import and export.
|
30
|
+
+ [**#256**](http://intranet.sfb673.org/issues/256): Resolves and exports Elan parent refs correctly.
|
31
|
+
+ [**#257**](http://intranet.sfb673.org/issues/257): Implements various missing ELAN (meta)data.
|
32
|
+
|
33
|
+
|
13
34
|
## 0.0.10
|
14
35
|
|
15
36
|
Completed on February 26 2014.
|
@@ -121,4 +142,4 @@ but **WITHOUT ANY WARRANTY**; without even the implied warranty of
|
|
121
142
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
122
143
|
GNU Lesser General Public License for more details.
|
123
144
|
|
124
|
-
See LICENSE.txt for further details.
|
145
|
+
See LICENSE.txt for further details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.11
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<FiestaDocument>
|
2
|
+
<ScaleSet>
|
3
|
+
<Scale id="timeline01" name="Timeline" unit="s" dimension="time"/>
|
4
|
+
</ScaleSet>
|
5
|
+
<LayerSet>
|
6
|
+
<Layer id="layer" name="Layer">
|
7
|
+
<PropertyMap key="layerProperties">
|
8
|
+
<Property key="elanTierType">TIME_SUBDIVISION</Property>
|
9
|
+
</PropertyMap>
|
10
|
+
</Layer>
|
11
|
+
</LayerSet>
|
12
|
+
<ItemSet/>
|
13
|
+
</FiestaDocument>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
## Release notes for version 0.0.11 – Complete ELAN and Praat support
|
2
|
+
|
3
|
+
+ [**#258**](http://intranet.sfb673.org/issues/258): Adds first working version of FancyWriter for creating formatted plain text file formats.
|
4
|
+
|
5
|
+
+ [**#154**](http://intranet.sfb673.org/issues/154): Adds export routine into the Praat ShortTextGrid format.
|
6
|
+
+ [**#155**](http://intranet.sfb673.org/issues/155): Adds TextGrid export functionality.
|
7
|
+
|
8
|
+
+ [**#156**](http://intranet.sfb673.org/issues/156): EAF export should now be complete, including metadata:
|
9
|
+
|
10
|
+
+ [**#234**](http://intranet.sfb673.org/issues/234): Spec test files are adopted to reflect additional ELAN features.
|
11
|
+
+ [**#248**](http://intranet.sfb673.org/issues/248): Layers now use property structures for additional configuration.
|
12
|
+
+ [**#251**](http://intranet.sfb673.org/issues/251): ELAN import now uses up-to-date method for adding layers.
|
13
|
+
+ [**#252**](http://intranet.sfb673.org/issues/252): Adds custom setter methods for identifiers in order to produce XML-valid IDs.
|
14
|
+
+ [**#253**](http://intranet.sfb673.org/issues/253): Fixes a bug where annotations with empty string values were skipped.
|
15
|
+
+ [**#255**](http://intranet.sfb673.org/issues/255): Persists the ANNOTATOR attribute from ELAN during import and export.
|
16
|
+
+ [**#256**](http://intranet.sfb673.org/issues/256): Resolves and exports Elan parent refs correctly.
|
17
|
+
+ [**#257**](http://intranet.sfb673.org/issues/257): Implements various missing ELAN (meta)data.
|
@@ -26,6 +26,13 @@ class Mexico::Fiesta::Interfaces::ElanInterface
|
|
26
26
|
include Singleton
|
27
27
|
include Mexico::FileSystem
|
28
28
|
|
29
|
+
CONSTRAINTS = {
|
30
|
+
'Included_In' => "Time alignable annotations within the parent annotation's time interval, gaps are allowed",
|
31
|
+
'Time_Subdivision' => "Time subdivision of parent annotation's time interval, no time gaps allowed within this interval",
|
32
|
+
'Symbolic_Subdivision' => 'Symbolic subdivision of a parent annotation. Annotations refering to the same parent are ordered',
|
33
|
+
'Symbolic_Association' => '1-1 association with a parent annotation'
|
34
|
+
}
|
35
|
+
|
29
36
|
def self.import(io=$stdin, params = {})
|
30
37
|
puts 'class method import'
|
31
38
|
instance.import(io, params)
|
@@ -36,7 +43,6 @@ class Mexico::Fiesta::Interfaces::ElanInterface
|
|
36
43
|
end
|
37
44
|
|
38
45
|
def import(io=$stdin, params = {})
|
39
|
-
puts 'instance method import'
|
40
46
|
|
41
47
|
io.rewind
|
42
48
|
|
@@ -45,6 +51,68 @@ class Mexico::Fiesta::Interfaces::ElanInterface
|
|
45
51
|
|
46
52
|
document = Mexico::FileSystem::FiestaDocument.new
|
47
53
|
|
54
|
+
sec_datamodel = document.head[Mexico::FileSystem::Section::DATA_MODEL]
|
55
|
+
|
56
|
+
sec_datamodel.properties << Mexico::FileSystem::Property.new('sourceFormat', 'ELAN/EAF')
|
57
|
+
sec_datamodel.properties << Mexico::FileSystem::Property.new('converterClass', 'Mexico::Fiesta::Interfaces::ElanInterface')
|
58
|
+
|
59
|
+
# import attributes on root element
|
60
|
+
|
61
|
+
xmldoc.xpath("/ANNOTATION_DOCUMENT").each do |annodoc|
|
62
|
+
# atts: DATE, AUTHOR, VERSION, FORMAT
|
63
|
+
# xmlns:xsi xsi:noNamespaceSchemaLocation
|
64
|
+
|
65
|
+
puts xmldoc.namespaces
|
66
|
+
sec_lifecycle = document.head[Mexico::FileSystem::Section::LIFECYCLE]
|
67
|
+
date = DateTime.iso8601(annodoc['DATE'])
|
68
|
+
sec_lifecycle.properties << Mexico::FileSystem::Property.new('creationDate', date)
|
69
|
+
puts date.class.name
|
70
|
+
sec_lifecycle.properties << Mexico::FileSystem::Property.new('authorKey', annodoc['AUTHOR'])
|
71
|
+
|
72
|
+
|
73
|
+
sec_datamodel.properties << Mexico::FileSystem::Property.new('annotationToolVersion', annodoc['VERSION'])
|
74
|
+
sec_datamodel.properties << Mexico::FileSystem::Property.new('annotationToolFormat', annodoc['FORMAT'])
|
75
|
+
sec_datamodel.properties << Mexico::FileSystem::Property.new('xmlSchemaDeclaration', xmldoc.namespaces['xmlns:xsi'])
|
76
|
+
sec_datamodel.properties << Mexico::FileSystem::Property.new('xsiNoNamespaceSchemaLocation', annodoc['xsi:noNamespaceSchemaLocation'])
|
77
|
+
|
78
|
+
annodoc.attributes.each do |a|
|
79
|
+
puts a
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# import heaader
|
84
|
+
# - @MEDIA_FILE
|
85
|
+
# - @TIME_UNITS
|
86
|
+
# - MEDIA DESCRIPTOR
|
87
|
+
# - PROPERTY/@name=lastUsedAnnotationId
|
88
|
+
|
89
|
+
xmldoc.xpath("//HEADER").each do |header|
|
90
|
+
header['MEDIA_FILE']
|
91
|
+
header['TIME_UNTIS']
|
92
|
+
|
93
|
+
document.head[Mexico::FileSystem::Section::MEDIA_CONTEXT].property_maps << Mexico::FileSystem::PropertyMap.new(key: 'referencedMedia')
|
94
|
+
refMediaMap = document.head[Mexico::FileSystem::Section::MEDIA_CONTEXT].property_maps.find{|m| m.key=='referencedMedia'}
|
95
|
+
datModelSec = document.head[Mexico::FileSystem::Section::DATA_MODEL]
|
96
|
+
|
97
|
+
refMediaMap.properties << Mexico::FileSystem::Property.new('primaryMediaUrl', header['MEDIA_FILE'])
|
98
|
+
|
99
|
+
# time units should go into another section!
|
100
|
+
datModelSec.properties << Mexico::FileSystem::Property.new('timeUnits', header['TIME_UNITS'])
|
101
|
+
|
102
|
+
header.xpath('./MEDIA_DESCRIPTOR').each_with_index do |mediafile,n|
|
103
|
+
file_map = Mexico::FileSystem::PropertyMap.new(key: "#{n}")
|
104
|
+
# prop = Mexico::FileSystem::Property.new('path', mediafile['RELATIVE_MEDIA_URL'])
|
105
|
+
#puts " %s : %s" % [prop.key, prop.value]
|
106
|
+
file_map.properties << Mexico::FileSystem::Property.new('path', mediafile['RELATIVE_MEDIA_URL'])
|
107
|
+
file_map.properties << Mexico::FileSystem::Property.new('mimeType', mediafile['MIME_TYPE'])
|
108
|
+
file_map.properties << Mexico::FileSystem::Property.new('uri', mediafile['MEDIA_URL'])
|
109
|
+
refMediaMap.property_maps << file_map
|
110
|
+
end
|
111
|
+
header.xpath('./PROPERTY').each do |property|
|
112
|
+
datModelSec.properties << Mexico::FileSystem::Property.new(property['NAME'], property.text)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
# actual data:
|
48
116
|
# 1. create a standard timeline
|
49
117
|
timeline = document.add_standard_timeline('s')
|
50
118
|
|
@@ -56,6 +124,53 @@ class Mexico::Fiesta::Interfaces::ElanInterface
|
|
56
124
|
timeslots[slot] = val
|
57
125
|
end
|
58
126
|
|
127
|
+
# read cv entries
|
128
|
+
|
129
|
+
# cvs = Hash.new
|
130
|
+
|
131
|
+
xmldoc.xpath("//CONTROLLED_VOCABULARY").each do |c|
|
132
|
+
container_map = Mexico::FileSystem::PropertyMap.new(key: c['CV_ID'])
|
133
|
+
metamap = Mexico::FileSystem::PropertyMap.new(key: 'info')
|
134
|
+
metamap.properties << Mexico::FileSystem::Property.new('identifier', c['CV_ID'])
|
135
|
+
metamap.properties << Mexico::FileSystem::Property.new('description', c['DESCRIPTION'])
|
136
|
+
valuemap = Mexico::FileSystem::PropertyMap.new(key: 'data')
|
137
|
+
c.xpath("./CV_ENTRY").each do |entry|
|
138
|
+
desc = entry['DESCRIPTION']
|
139
|
+
val = entry.text
|
140
|
+
valprop = Mexico::FileSystem::PropertyMap.new
|
141
|
+
valprop.properties << Mexico::FileSystem::Property.new('description', desc)
|
142
|
+
valprop.properties << Mexico::FileSystem::Property.new('value', val)
|
143
|
+
valuemap.property_maps << valprop
|
144
|
+
end
|
145
|
+
container_map.property_maps << metamap
|
146
|
+
container_map.property_maps << valuemap
|
147
|
+
document.head.section(Mexico::FileSystem::Section::VOCABULARIES).property_maps << container_map
|
148
|
+
end
|
149
|
+
|
150
|
+
# Read ling type entries
|
151
|
+
lingTypes = Hash.new
|
152
|
+
xmldoc.xpath("//LINGUISTIC_TYPE").each do |lingtype|
|
153
|
+
cnstrs, cntvoc = nil
|
154
|
+
cnstrs = lingtype['CONSTRAINTS'] unless lingtype['CONSTRAINTS'].nil?
|
155
|
+
graphr = lingtype['GRAPHIC_REFERENCES']=="true" ? true : false
|
156
|
+
lngtid = lingtype['LINGUISTIC_TYPE_ID']
|
157
|
+
timeal = lingtype['TIME_ALIGNABLE']=="true" ? true : false
|
158
|
+
cntvoc = lingtype['CONTROLLED_VOCABULARY_REF'] unless lingtype['CONTROLLED_VOCABULARY_REF'].nil?
|
159
|
+
lingTypeEntry = { constraints: cnstrs, graphicReferences: graphr, timeAlignable: timeal, controlledVocabulary: cntvoc }
|
160
|
+
lingTypes[lngtid] = lingTypeEntry
|
161
|
+
end
|
162
|
+
|
163
|
+
lingTypes.each do |key,val|
|
164
|
+
sec = document.head[Mexico::FileSystem::Section::LAYER_TYPES]
|
165
|
+
pmap = Mexico::FileSystem::PropertyMap.new(key: key)
|
166
|
+
val.each do |skey,sval|
|
167
|
+
unless sval.nil?
|
168
|
+
pmap.properties << Mexico::FileSystem::Property::new(skey,sval)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
sec.property_maps << pmap
|
172
|
+
end
|
173
|
+
|
59
174
|
# create temporary hash for storage of layers
|
60
175
|
layerHash = Hash.new
|
61
176
|
|
@@ -65,23 +180,29 @@ class Mexico::Fiesta::Interfaces::ElanInterface
|
|
65
180
|
tierID = t["TIER_ID"]
|
66
181
|
puts 'Read layers, %s' % tierID
|
67
182
|
|
68
|
-
layer =
|
69
|
-
name: tierID,
|
70
|
-
document: document)
|
183
|
+
layer = document.add_layer(identifier: tierID, name: tierID)
|
71
184
|
#layer.name = tierID
|
72
185
|
#layer.id = ToE::Util::to_xml_id(tierID)
|
73
186
|
|
74
|
-
|
187
|
+
layer.add_property Mexico::FileSystem::Property.new('elanTierType', t['LINGUISTIC_TYPE_REF'])
|
188
|
+
|
189
|
+
if t.attributes.has_key?('ANNOTATOR')
|
190
|
+
layer.add_property Mexico::FileSystem::Property.new('annotator', t['ANNOTATOR'])
|
191
|
+
end
|
192
|
+
# document.layers << layer
|
75
193
|
|
76
|
-
puts t.attributes
|
77
|
-
puts t.attributes.has_key?('PARENT_REF')
|
194
|
+
puts "Attributes: %s" % t.attributes.to_s
|
195
|
+
puts "Parent ref? %s" % t.attributes.has_key?('PARENT_REF')
|
78
196
|
if t.attributes.has_key?('PARENT_REF')
|
79
197
|
# puts "TATT: %s" % t['PARENT_REF']
|
80
|
-
document.layers.each do |l|
|
81
|
-
|
82
|
-
end
|
83
|
-
|
84
|
-
puts
|
198
|
+
# document.layers.each do |l|
|
199
|
+
# puts "LAYER %s %s" % [l.identifier, l.name]
|
200
|
+
# end
|
201
|
+
puts 'ID of parent layer %s' % t['PARENT_REF']
|
202
|
+
puts 'ID, xmlified %s' % Mexico::Util::to_xml_id(t['PARENT_REF'])
|
203
|
+
puts 'available ids: %s' % (document.layers.collect{|l| l.identifier}).join(' ')
|
204
|
+
parent_layer = document.get_layer_by_id(Mexico::Util::to_xml_id(t['PARENT_REF']))
|
205
|
+
puts "Found parent layer: %s" % parent_layer
|
85
206
|
if parent_layer
|
86
207
|
layer_connector = Mexico::FileSystem::LayerConnector.new parent_layer, layer, {
|
87
208
|
identifier: "#{parent_layer.identifier}_TO_#{layer.identifier}",
|
@@ -101,7 +222,7 @@ class Mexico::Fiesta::Interfaces::ElanInterface
|
|
101
222
|
if anno.name == "ALIGNABLE_ANNOTATION"
|
102
223
|
|
103
224
|
# puts anno.xpath("./ANNOTATION_VALUE/text()").first
|
104
|
-
if annoVal!=nil && annoVal.strip != ""
|
225
|
+
if annoVal!=nil # && annoVal.strip != ""
|
105
226
|
i.add_interval_link Mexico::FileSystem::IntervalLink.new(identifier: "#{i.identifier}-int",
|
106
227
|
min: timeslots[anno["TIME_SLOT_REF1"]].to_f,
|
107
228
|
max: timeslots[anno["TIME_SLOT_REF2"]].to_f,
|
@@ -110,13 +231,20 @@ class Mexico::Fiesta::Interfaces::ElanInterface
|
|
110
231
|
end
|
111
232
|
if anno.name == "REF_ANNOTATION"
|
112
233
|
|
113
|
-
puts pp anno
|
114
|
-
puts document.items.collect{|x| x.identifier}.join(', ')
|
115
|
-
puts '-'*80
|
234
|
+
#puts pp anno
|
235
|
+
#puts document.items.collect{|x| x.identifier}.join(', ')
|
236
|
+
#puts '-'*80
|
116
237
|
|
117
238
|
i.add_item_link Mexico::FileSystem::ItemLink.new(identifier: "#{i.identifier}-itm",
|
118
239
|
target_object: document.items({identifier: anno["ANNOTATION_REF"]}).first,
|
119
240
|
role: Mexico::FileSystem::ItemLink::ROLE_PARENT)
|
241
|
+
|
242
|
+
# @todo add previous anno if present
|
243
|
+
if anno.has_attribute?('PREVIOUS_ANNOTATION')
|
244
|
+
i.add_item_link Mexico::FileSystem::ItemLink.new(identifier: "#{i.identifier}-pre",
|
245
|
+
target_object: document.items({identifier: anno["PREVIOUS_ANNOTATION"]}).first,
|
246
|
+
role: Mexico::FileSystem::ItemLink::ROLE_PREDECESSOR)
|
247
|
+
end
|
120
248
|
end
|
121
249
|
i.add_layer_link Mexico::FileSystem::LayerLink.new(identifier: "#{i.identifier}-lay",
|
122
250
|
target_object: layer)
|
@@ -140,7 +268,220 @@ class Mexico::Fiesta::Interfaces::ElanInterface
|
|
140
268
|
|
141
269
|
def export(doc, io=$stdout, params = {})
|
142
270
|
|
271
|
+
# Create an XML builder object that serialises into an XML structure
|
272
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
273
|
+
|
274
|
+
sec_datamodel = doc.head[Mexico::FileSystem::Section::DATA_MODEL]
|
275
|
+
sec_lifecycle = doc.head[Mexico::FileSystem::Section::LIFECYCLE]
|
276
|
+
|
277
|
+
date = sec_lifecycle['creationDate'].value
|
278
|
+
author = sec_lifecycle['authorKey'].value
|
279
|
+
format = sec_datamodel['annotationToolFormat'].value
|
280
|
+
version = sec_datamodel['annotationToolVersion'].value
|
281
|
+
schema_location = sec_datamodel['xsiNoNamespaceSchemaLocation'].value
|
282
|
+
ad_attrs = {
|
283
|
+
DATE: date, AUTHOR: author,
|
284
|
+
FORMAT: format, VERSION: version,
|
285
|
+
'xmlns:xsi'=>'http://www.w3.org/2001/XMLSchema-instance',
|
286
|
+
'xsi:noNamespaceSchemaLocation' => schema_location
|
287
|
+
}
|
288
|
+
#xml.root() do
|
289
|
+
#end
|
290
|
+
xml.ANNOTATION_DOCUMENT(ad_attrs) do
|
291
|
+
# @TODO implement the export of the header
|
292
|
+
mediaFile = ''
|
293
|
+
mediaFile = doc.head[Mexico::FileSystem::Section::MEDIA_CONTEXT]['primaryMediaUrl'].value unless doc.head[Mexico::FileSystem::Section::MEDIA_CONTEXT]['primaryMediaUrl'].nil?
|
294
|
+
timeUnits = doc.head[Mexico::FileSystem::Section::DATA_MODEL]['timeUnits'].value
|
295
|
+
xml.HEADER({MEDIA_FILE: mediaFile, TIME_UNITS: timeUnits}) do
|
296
|
+
doc.head[Mexico::FileSystem::Section::MEDIA_CONTEXT]['referencedMedia'].property_maps.each do |m|
|
297
|
+
uri = m['uri'].value
|
298
|
+
path = m['path'].value
|
299
|
+
mimeType = m['mimeType'].value
|
300
|
+
|
301
|
+
xml.MEDIA_DESCRIPTOR({MEDIA_URL: uri, MIME_TYPE: mimeType, RELATIVE_MEDIA_URL: path})
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
# create the time stamp data structure
|
306
|
+
time_hash = Hash.new
|
307
|
+
counter = 1
|
308
|
+
|
309
|
+
# @todo #254 rework to use unit conversions!
|
310
|
+
doc.items.each do |item|
|
311
|
+
item.point_links.each do |pl|
|
312
|
+
unless time_hash.has_key?(pl.point)
|
313
|
+
time_hash[pl.point] = "ts#{counter}"
|
314
|
+
counter += 1
|
315
|
+
end
|
316
|
+
end
|
317
|
+
item.interval_links.each do |il|
|
318
|
+
unless time_hash.has_key?(il.min)
|
319
|
+
time_hash[il.min] = "ts#{counter}"
|
320
|
+
counter += 1
|
321
|
+
end
|
322
|
+
unless time_hash.has_key?(il.max)
|
323
|
+
time_hash[il.max] = "ts#{counter}"
|
324
|
+
counter += 1
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
xml.TIME_ORDER do
|
330
|
+
# collect all timestamps
|
331
|
+
# create a hash for them
|
332
|
+
time_hash.each do |tkey, tval|
|
333
|
+
xml.TIME_SLOT({'TIME_SLOT_ID' => tval, 'TIME_VALUE'=>tkey.to_i.to_s})
|
334
|
+
end
|
335
|
+
end
|
336
|
+
inverted_time_hash = time_hash.invert
|
337
|
+
|
338
|
+
|
339
|
+
# read ling types from map
|
340
|
+
ling_types = Hash.new
|
341
|
+
|
342
|
+
lt_section = doc.head.section(Mexico::FileSystem::Section::LAYER_TYPES)
|
343
|
+
lt_section.property_maps.each do |pm|
|
344
|
+
key = pm.key
|
345
|
+
puts key
|
346
|
+
|
347
|
+
pm.properties.each do |p|
|
348
|
+
puts " .. %s -> %s" % [p.key, p.value]
|
349
|
+
|
350
|
+
end
|
351
|
+
# puts pm.size
|
352
|
+
ling_type = Hash.new
|
353
|
+
|
354
|
+
if pm.has_key?('constraints')
|
355
|
+
ling_type['constraints'] = pm['constraints'].value
|
356
|
+
end
|
357
|
+
if pm.has_key?('graphicReferences')
|
358
|
+
ling_type['graphicReferences'] = pm['graphicReferences'].value
|
359
|
+
end
|
360
|
+
if pm.has_key?('timeAlignable')
|
361
|
+
ling_type['timeAlignable'] = pm['timeAlignable'].value
|
362
|
+
end
|
363
|
+
if pm.has_key?('controlledVocabulary')
|
364
|
+
ling_type['controlledVocabulary'] = pm['controlledVocabulary'].value
|
365
|
+
end
|
366
|
+
ling_types[key] = ling_type
|
367
|
+
end
|
368
|
+
puts ling_types
|
369
|
+
|
370
|
+
|
371
|
+
|
372
|
+
# export layer by layer
|
373
|
+
# caveat: only annotations with at least one layer link will be exported.
|
374
|
+
# caveat 2: annotations with multiple layer links will be exported multiple times.
|
375
|
+
|
376
|
+
|
377
|
+
|
378
|
+
doc.layers.each do |layer|
|
379
|
+
ling_type = layer.properties['elanTierType'].value
|
380
|
+
ling_type_object = doc.head[Mexico::FileSystem::Section::LAYER_TYPES].property_maps.find{|m| m.key == ling_type}
|
381
|
+
puts "ling type object %s" % ling_type_object
|
382
|
+
constraint = ling_type_object['constraints']
|
383
|
+
unless constraint.nil?
|
384
|
+
constraint = constraint.value
|
385
|
+
end
|
386
|
+
attrs = {TIER_ID: layer.name, LINGUISTIC_TYPE_REF: ling_type}
|
387
|
+
|
388
|
+
annotator = layer.properties['annotator'].value
|
389
|
+
attrs.merge!({ANNOTATOR: annotator}) unless annotator.nil?
|
390
|
+
|
391
|
+
# check if this layer is the child of another one.
|
392
|
+
# if yes: add attribute PARENT_REF
|
393
|
+
|
394
|
+
# find a parent layer
|
395
|
+
parent_id=nil
|
396
|
+
parent_connectors = doc.layer_connectors.select{|c| c.target == layer}
|
397
|
+
if parent_connectors.size>0
|
398
|
+
parent_id = parent_connectors.first.source.name
|
399
|
+
attrs.merge!({PARENT_REF: parent_id})
|
400
|
+
end
|
401
|
+
|
402
|
+
tier = xml.TIER(attrs) do
|
403
|
+
puts "inside tier"
|
404
|
+
layer.items.each do |item|
|
405
|
+
xml.ANNOTATION do
|
406
|
+
# depending on the layer type, use either ALIGNABLE or REF annotations
|
407
|
+
if %w(Symbolic_Subdivision Symbolic_Association).include?(constraint)
|
408
|
+
ref_attrs = {ANNOTATION_ID: item.identifier}
|
409
|
+
parent_ref = item.item_links.find{|l| l.role == Mexico::FileSystem::ItemLink::ROLE_PARENT}
|
410
|
+
unless parent_ref.nil?
|
411
|
+
ref_attrs.merge!({ANNOTATION_REF: parent_ref.target_item.identifier})
|
412
|
+
end
|
413
|
+
pre_ref = item.item_links.find{|l| l.role == Mexico::FileSystem::ItemLink::ROLE_PREDECESSOR}
|
414
|
+
unless pre_ref.nil?
|
415
|
+
ref_attrs.merge!({PREVIOUS_ANNOTATION: pre_ref.target_item.identifier})
|
416
|
+
end
|
417
|
+
xml.REF_ANNOTATION(ref_attrs) do
|
418
|
+
xml.ANNOTATION_VALUE item.data.string_value
|
419
|
+
end
|
420
|
+
else
|
421
|
+
tsref1, tsref2 = nil
|
422
|
+
unless item.interval_links.empty?
|
423
|
+
tsref1 = time_hash[item.interval_links.first.min]
|
424
|
+
tsref2 = time_hash[item.interval_links.first.max]
|
425
|
+
end
|
426
|
+
xml.ALIGNABLE_ANNOTATION({'ANNOTATION_ID'=>item.identifier,TIME_SLOT_REF1: tsref1,TIME_SLOT_REF2: tsref2}) do
|
427
|
+
xml.ANNOTATION_VALUE item.data.string_value
|
428
|
+
end
|
429
|
+
end
|
430
|
+
end
|
431
|
+
end
|
432
|
+
end
|
433
|
+
puts "%s :: %s" % [tier["TIER_ID"], layer.identifier]
|
434
|
+
end
|
435
|
+
|
436
|
+
# @todo #257 a :: LINGUISTIC_TYPE
|
437
|
+
types = doc.head[Mexico::FileSystem::Section::LAYER_TYPES]
|
438
|
+
types.property_maps.each do |tp|
|
439
|
+
puts tp.class.name
|
440
|
+
puts tp.properties.size
|
441
|
+
puts tp.property_maps.size
|
442
|
+
puts "PROPMAP: %s" % tp.properties.collect{|m| "#{m.key}: #{m.value}"}.join(' ')
|
443
|
+
puts "TIME ALIGNABLE? %s" % tp.has_key?('timeAlignable')
|
444
|
+
puts "TIME ALIGNABLE? %s" % tp['timeAlignable']
|
445
|
+
# puts "TIME ALIGNABLE? %s" % tp['timeAlignable'].value
|
446
|
+
|
447
|
+
time_alignable = tp.has_key?('timeAlignable') ? tp['timeAlignable'].value : nil
|
448
|
+
graphic_references = tp.has_key?('graphicReferences') ? tp['graphicReferences'].value : nil
|
449
|
+
controlled_vocabulary_ref = tp.has_key?('controlledVocabulary') ? tp['controlledVocabulary'].value : nil
|
450
|
+
constraints = tp.has_key?('constraints') ? tp['constraints'].value : nil
|
451
|
+
|
452
|
+
puts "TIME ALIGNABLE? %s" % time_alignable
|
453
|
+
|
454
|
+
attrs = {LINGUISTIC_TYPE_ID: tp.key}
|
455
|
+
attrs.merge!({ TIME_ALIGNABLE: time_alignable}) unless time_alignable.nil?
|
456
|
+
attrs.merge!({ GRAPHIC_REFERENCES: graphic_references}) unless graphic_references.nil?
|
457
|
+
attrs.merge!({CONTROLLED_VOCABULARY_REF: controlled_vocabulary_ref}) unless controlled_vocabulary_ref.nil?
|
458
|
+
attrs.merge!({ CONSTRAINTS: constraints}) unless constraints.nil?
|
459
|
+
|
460
|
+
xml.LINGUISTIC_TYPE(attrs)
|
461
|
+
end
|
462
|
+
|
463
|
+
# Exports ELAN constraints.
|
464
|
+
# These are static, so the same for all documents.
|
465
|
+
Mexico::Fiesta::Interfaces::ElanInterface::CONSTRAINTS.each do |conk,conv|
|
466
|
+
xml.CONSTRAINT STEREOTYPE: conk, DESCRIPTION: conv
|
467
|
+
end
|
468
|
+
|
469
|
+
# CONTROLLED_VOCABULARY
|
470
|
+
vocs = doc.head[Mexico::FileSystem::Section::VOCABULARIES]
|
471
|
+
vocs.property_maps.each do |voc|
|
472
|
+
metamap = voc['info']
|
473
|
+
datamap = voc['data']
|
474
|
+
xml.CONTROLLED_VOCABULARY({CV_ID: voc.key, DESCRIPTION: metamap['description'].value }) do
|
475
|
+
datamap.property_maps.each do |cv_entry|
|
476
|
+
xml.CV_ENTRY(cv_entry['value'].value, {DESCRIPTION: cv_entry['description'].value})
|
477
|
+
end
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
end
|
482
|
+
end
|
483
|
+
io << builder.to_xml
|
143
484
|
end
|
144
485
|
|
145
486
|
|
146
|
-
end
|
487
|
+
end
|
@@ -99,4 +99,63 @@ class Mexico::Fiesta::Interfaces::ShortTextGridInterface
|
|
99
99
|
fdoc
|
100
100
|
end
|
101
101
|
|
102
|
+
def export(doc, io=$stdout, params = {})
|
103
|
+
Mexico::Util::FancyWriter.new(io) do
|
104
|
+
line 'File type = "ooTextFile"'
|
105
|
+
line 'Object class = "TextGrid"'
|
106
|
+
line
|
107
|
+
|
108
|
+
# overall min and max values
|
109
|
+
total_item_links = doc.items.collect{|i| i.interval_links}.flatten
|
110
|
+
total_min = total_item_links.collect{|l| l.min}.min
|
111
|
+
total_max = total_item_links.collect{|l| l.max}.max
|
112
|
+
line total_min, total_max
|
113
|
+
line '<exists>'
|
114
|
+
line doc.layers.size
|
115
|
+
|
116
|
+
# FOREACH layer : print layer header block
|
117
|
+
doc.layers.each do |layer|
|
118
|
+
# "IntervalTier", "name", min, max, annocount
|
119
|
+
|
120
|
+
line '"IntervalTier"'
|
121
|
+
line %Q("#{layer.name}")
|
122
|
+
layer_item_links = doc.items.collect{|i| i.interval_links}.flatten
|
123
|
+
layer_min = layer_item_links.collect{|l| l.min}.min
|
124
|
+
layer_max = layer_item_links.collect{|l| l.max}.max
|
125
|
+
line layer_min, layer_max
|
126
|
+
|
127
|
+
# FOREACH item in layer : min, max, value
|
128
|
+
sorted_items = layer.items.sort{|i,j| i.interval_links.first.min <=> i.interval_links.first.min}
|
129
|
+
time_points = [total_min, total_max, layer_min, layer_max]
|
130
|
+
sorted_items.each do |i|
|
131
|
+
time_points << i.interval_links.first.min
|
132
|
+
time_points << i.interval_links.first.max
|
133
|
+
end
|
134
|
+
time_points.uniq!.sort!
|
135
|
+
# print effective number of annotations
|
136
|
+
line time_points.size-1
|
137
|
+
time_points.each_with_index do |current_point, n|
|
138
|
+
next_point = nil
|
139
|
+
unless n == time_points.size-1
|
140
|
+
next_point = time_points[n+1]
|
141
|
+
end
|
142
|
+
unless next_point.nil?
|
143
|
+
#puts "-"*48
|
144
|
+
#puts "TL: %20.18f - %20.18f" % [current_point, next_point]
|
145
|
+
#sorted_items.each do |it|
|
146
|
+
# puts "IT: %20.18f - %20.18f -- %20.18f - %20.18f, %s" % [it.interval_links.first.min, it.interval_links.first.max, (it.interval_links.first.min-current_point), (it.interval_links.first.max-next_point), ((it.interval_links.first.min-current_point).abs<0.00001 && (it.interval_links.first.max-next_point).abs<0.00001)]
|
147
|
+
#end
|
148
|
+
item = sorted_items.select{|i| (i.interval_links.first.min-current_point).abs<0.00001 && (i.interval_links.first.max-next_point).abs<0.00001}.first
|
149
|
+
#puts item
|
150
|
+
line current_point, next_point
|
151
|
+
if item.nil?
|
152
|
+
line '""'
|
153
|
+
else
|
154
|
+
line %Q("#{item.data.string_value}")
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
102
161
|
end
|
@@ -70,14 +70,11 @@ class Mexico::Fiesta::Interfaces::TextGridInterface
|
|
70
70
|
layer = fdoc.add_layer({identifier:tierName, name:tierName})
|
71
71
|
|
72
72
|
for anno_num in (1..tierSize)
|
73
|
-
|
74
73
|
io.gets
|
75
74
|
annoMin = io.gets.match(/(\d+(\.\d+)?)/)[1].to_f
|
76
75
|
annoMax = io.gets.match(/(\d+(\.\d+)?)/)[1].to_f
|
77
76
|
annoVal = io.gets.match(/"(.*)"/)[1]
|
78
|
-
|
79
77
|
if annoVal.strip != ""
|
80
|
-
|
81
78
|
item = fdoc.add_item({identifier:"l#{tier_num}a#{anno_num}"}) do |i|
|
82
79
|
i.add_interval_link IntervalLink.new(
|
83
80
|
identifier:"#{i.identifier}-il",
|
@@ -89,17 +86,82 @@ class Mexico::Fiesta::Interfaces::TextGridInterface
|
|
89
86
|
identifier:"#{i.identifier}-ll",
|
90
87
|
target_object: layer )
|
91
88
|
end
|
92
|
-
|
93
|
-
puts item
|
94
|
-
|
89
|
+
# puts item
|
95
90
|
end
|
96
|
-
|
97
91
|
end
|
98
|
-
|
99
92
|
end
|
100
|
-
|
101
93
|
fdoc
|
102
|
-
|
103
94
|
end
|
104
95
|
|
96
|
+
|
97
|
+
def export(doc, io=$stdout, params = {})
|
98
|
+
Mexico::Util::FancyWriter.new(io) do
|
99
|
+
line 'File type = "ooTextFile"'
|
100
|
+
line 'Object class = "TextGrid"'
|
101
|
+
line
|
102
|
+
|
103
|
+
# overall min and max values
|
104
|
+
total_item_links = doc.items.collect{|i| i.interval_links}.flatten
|
105
|
+
total_min = total_item_links.collect{|l| l.min}.min
|
106
|
+
total_max = total_item_links.collect{|l| l.max}.max
|
107
|
+
line "xmin = %f" % total_min
|
108
|
+
line "xmax = %f" % total_max
|
109
|
+
line 'tiers? <exists>'
|
110
|
+
line "size = %i" % doc.layers.size
|
111
|
+
line 'item []:'
|
112
|
+
indent 4 do
|
113
|
+
# FOREACH layer : print layer header block
|
114
|
+
doc.layers.each_with_index do |layer,layer_index|
|
115
|
+
line 'item [%i]:' % (layer_index+1)
|
116
|
+
|
117
|
+
indent 4 do
|
118
|
+
# "IntervalTier", "name", min, max, annocount
|
119
|
+
line 'class = "IntervalTier"'
|
120
|
+
line %Q(name = "#{layer.name}")
|
121
|
+
layer_item_links = doc.items.collect{|i| i.interval_links}.flatten
|
122
|
+
layer_min = layer_item_links.collect{|l| l.min}.min
|
123
|
+
layer_max = layer_item_links.collect{|l| l.max}.max
|
124
|
+
line "xmin = %f" % layer_min
|
125
|
+
line "xmax = %f" % layer_max
|
126
|
+
|
127
|
+
# FOREACH item in layer : min, max, value
|
128
|
+
sorted_items = layer.items.sort{|i,j| i.interval_links.first.min <=> i.interval_links.first.min}
|
129
|
+
time_points = [total_min, total_max, layer_min, layer_max]
|
130
|
+
sorted_items.each do |i|
|
131
|
+
time_points << i.interval_links.first.min
|
132
|
+
time_points << i.interval_links.first.max
|
133
|
+
end
|
134
|
+
time_points.uniq!.sort!
|
135
|
+
# print effective number of annotations
|
136
|
+
line "intervals: size = %i" % (time_points.size-1)
|
137
|
+
time_points.each_with_index do |current_point, n|
|
138
|
+
next_point = nil
|
139
|
+
unless n == time_points.size-1
|
140
|
+
next_point = time_points[n+1]
|
141
|
+
end
|
142
|
+
unless next_point.nil?
|
143
|
+
#puts "-"*48
|
144
|
+
#puts "TL: %20.18f - %20.18f" % [current_point, next_point]
|
145
|
+
#sorted_items.each do |it|
|
146
|
+
# puts "IT: %20.18f - %20.18f -- %20.18f - %20.18f, %s" % [it.interval_links.first.min, it.interval_links.first.max, (it.interval_links.first.min-current_point), (it.interval_links.first.max-next_point), ((it.interval_links.first.min-current_point).abs<0.00001 && (it.interval_links.first.max-next_point).abs<0.00001)]
|
147
|
+
#end
|
148
|
+
line 'intervals [%i]:' % (n+1)
|
149
|
+
indent 4 do
|
150
|
+
item = sorted_items.select{|i| (i.interval_links.first.min-current_point).abs<0.00001 && (i.interval_links.first.max-next_point).abs<0.00001}.first
|
151
|
+
#puts item
|
152
|
+
line 'xmin = %f' % current_point
|
153
|
+
line 'xmax = %f' % next_point
|
154
|
+
if item.nil?
|
155
|
+
line 'text = ""'
|
156
|
+
else
|
157
|
+
line %Q(text = "#{item.data.string_value}")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
105
167
|
end
|
@@ -30,4 +30,19 @@ class Mexico::FileSystem::Head
|
|
30
30
|
# many HeadSections with keys
|
31
31
|
xml_accessor :sections, :as => [::Mexico::FileSystem::Section], :from => "Section"
|
32
32
|
|
33
|
+
def initialize(args={})
|
34
|
+
@sections = []
|
35
|
+
::Mexico::FileSystem::Section::SECTION_KEYS.each do |key|
|
36
|
+
@sections << ::Mexico::FileSystem::Section.new(key)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def [](key)
|
41
|
+
sections.find{|x| x.key == key }
|
42
|
+
end
|
43
|
+
|
44
|
+
def section(key)
|
45
|
+
sections.find{|x| x.key == key }
|
46
|
+
end
|
47
|
+
|
33
48
|
end
|
@@ -23,7 +23,11 @@ class Mexico::FileSystem::IntervalLink
|
|
23
23
|
xml_name "IntervalLink"
|
24
24
|
|
25
25
|
# identifier
|
26
|
-
|
26
|
+
xml_reader :identifier, :from => '@id'
|
27
|
+
|
28
|
+
def identifier=(new_id)
|
29
|
+
@identifier = Mexico::Util::to_xml_id(new_id)
|
30
|
+
end
|
27
31
|
|
28
32
|
# type Float
|
29
33
|
xml_accessor :min, :as => Float, :from => "@min"
|
@@ -22,7 +22,11 @@ class Mexico::FileSystem::Item
|
|
22
22
|
include ::ROXML
|
23
23
|
xml_name 'I'
|
24
24
|
|
25
|
-
|
25
|
+
xml_reader :identifier, :from => '@id'
|
26
|
+
|
27
|
+
def identifier=(new_id)
|
28
|
+
@identifier = Mexico::Util::to_xml_id(new_id)
|
29
|
+
end
|
26
30
|
|
27
31
|
# @todo compound links (later)
|
28
32
|
|
@@ -35,7 +35,11 @@ class Mexico::FileSystem::ItemLink
|
|
35
35
|
xml_name 'ItemLink'
|
36
36
|
|
37
37
|
# identifier
|
38
|
-
|
38
|
+
xml_reader :identifier, :from => '@id'
|
39
|
+
|
40
|
+
def identifier=(new_id)
|
41
|
+
@identifier = Mexico::Util::to_xml_id(new_id)
|
42
|
+
end
|
39
43
|
|
40
44
|
# type String
|
41
45
|
xml_accessor :role, :from => '@role'
|
@@ -21,9 +21,16 @@ class ::Mexico::FileSystem::Layer
|
|
21
21
|
|
22
22
|
include ROXML
|
23
23
|
|
24
|
-
|
24
|
+
xml_reader :identifier, :from => '@id'
|
25
|
+
|
26
|
+
def identifier=(new_id)
|
27
|
+
@identifier = Mexico::Util::to_xml_id(new_id)
|
28
|
+
end
|
29
|
+
|
25
30
|
xml_accessor :name, :from => '@name'
|
26
31
|
|
32
|
+
xml_accessor :properties, :as => ::Mexico::FileSystem::PropertyMap, :from => "PropertyMap"
|
33
|
+
|
27
34
|
attr_accessor :document
|
28
35
|
|
29
36
|
# POSEIdON-based RDF augmentation
|
@@ -42,7 +49,14 @@ class ::Mexico::FileSystem::Layer
|
|
42
49
|
if self.respond_to?("#{k}=")
|
43
50
|
send("#{k}=", v)
|
44
51
|
end
|
52
|
+
|
53
|
+
@properties = Mexico::FileSystem::PropertyMap.new
|
45
54
|
end
|
55
|
+
|
56
|
+
if properties.nil?
|
57
|
+
properties = ::Mexico::FileSystem::PropertyMap.new(key: 'layerProperties')
|
58
|
+
end
|
59
|
+
|
46
60
|
end
|
47
61
|
|
48
62
|
def items
|
@@ -85,5 +99,9 @@ class ::Mexico::FileSystem::Layer
|
|
85
99
|
end
|
86
100
|
end
|
87
101
|
|
102
|
+
def add_property(prop)
|
103
|
+
properties.properties << prop
|
104
|
+
end
|
105
|
+
|
88
106
|
|
89
107
|
end
|
@@ -22,7 +22,12 @@ class Mexico::FileSystem::LayerConnector
|
|
22
22
|
|
23
23
|
include ROXML
|
24
24
|
|
25
|
-
|
25
|
+
xml_reader :identifier, :from => '@id'
|
26
|
+
|
27
|
+
def identifier=(new_id)
|
28
|
+
@identifier = Mexico::Util::to_xml_id(new_id)
|
29
|
+
end
|
30
|
+
|
26
31
|
xml_accessor :name, :from => '@name'
|
27
32
|
|
28
33
|
xml_accessor :source_id, :from => '@source'
|
@@ -23,7 +23,11 @@ class Mexico::FileSystem::LayerLink
|
|
23
23
|
xml_name 'LayerLink'
|
24
24
|
|
25
25
|
# identifier
|
26
|
-
|
26
|
+
xml_reader :identifier, :from => '@id'
|
27
|
+
|
28
|
+
def identifier=(new_id)
|
29
|
+
@identifier = Mexico::Util::to_xml_id(new_id)
|
30
|
+
end
|
27
31
|
|
28
32
|
xml_accessor :role, :from => '@role'
|
29
33
|
|
@@ -23,7 +23,11 @@ class Mexico::FileSystem::PointLink
|
|
23
23
|
xml_name "PointLink"
|
24
24
|
|
25
25
|
# identifier
|
26
|
-
|
26
|
+
xml_reader :identifier, :from => '@id'
|
27
|
+
|
28
|
+
def identifier=(new_id)
|
29
|
+
@identifier = Mexico::Util::to_xml_id(new_id)
|
30
|
+
end
|
27
31
|
|
28
32
|
# type Float
|
29
33
|
xml_accessor :point, :as => Float, :from => "@point"
|
@@ -28,8 +28,22 @@ class Mexico::FileSystem::Property
|
|
28
28
|
xml_name 'Property'
|
29
29
|
|
30
30
|
xml_accessor :key, :from => '@key'
|
31
|
-
|
32
31
|
xml_accessor :value, :from => :content
|
33
32
|
|
33
|
+
def initialize(arg1=nil, arg2=nil)
|
34
|
+
puts "Property init - %s : %s" % [arg1, arg2]
|
35
|
+
if arg1.respond_to?(:has_key?)
|
36
|
+
args.each do |k,v|
|
37
|
+
if self.respond_to?("#{k}=")
|
38
|
+
send("#{k}=", v)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
else
|
42
|
+
unless (arg1.nil? || arg2.nil?)
|
43
|
+
self.key = arg1
|
44
|
+
self.value = arg2
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
34
48
|
|
35
49
|
end
|
@@ -34,4 +34,42 @@ class Mexico::FileSystem::PropertyMap
|
|
34
34
|
|
35
35
|
attr_accessor :values
|
36
36
|
|
37
|
+
def initialize(args={})
|
38
|
+
args.each do |k,v|
|
39
|
+
if self.respond_to?("#{k}=")
|
40
|
+
send("#{k}=", v)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
@properties = []
|
44
|
+
@property_maps = []
|
45
|
+
end
|
46
|
+
|
47
|
+
def has_key?(p_key)
|
48
|
+
# compare_list(p_key)
|
49
|
+
return true if properties.any?{|x| x.key.to_sym == p_key.to_sym}
|
50
|
+
return true if property_maps.any?{|x| x.key.to_sym == p_key.to_sym}
|
51
|
+
false
|
52
|
+
end
|
53
|
+
|
54
|
+
def [](p_key)
|
55
|
+
# compare_list(p_key)
|
56
|
+
if properties.any?{|x| x.key.to_sym == p_key.to_sym}
|
57
|
+
return properties.find{|x| x.key.to_sym == p_key.to_sym}
|
58
|
+
end
|
59
|
+
if property_maps.any?{|x| x.key.to_sym == p_key.to_sym}
|
60
|
+
return property_maps.find{|x| x.key.to_sym == p_key.to_sym}
|
61
|
+
end
|
62
|
+
return nil
|
63
|
+
end
|
64
|
+
|
65
|
+
def compare_list(p_key)
|
66
|
+
puts " <=> %s :: %s" % %w(ENTRY COMPARE_VAL)
|
67
|
+
properties.each do |p|
|
68
|
+
puts " <=> >%s< :: >%s< - %s" % [p.key, p_key, (p.key.to_sym==p_key.to_sym)]
|
69
|
+
end
|
70
|
+
property_maps.each do |p|
|
71
|
+
puts " <=> >%s< :: >%s< - %s" % [p.key, p_key, (p.key==p_key)]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
37
75
|
end
|
@@ -26,7 +26,12 @@ class Mexico::FileSystem::Scale
|
|
26
26
|
include ::ROXML
|
27
27
|
xml_name 'Scale'
|
28
28
|
|
29
|
-
|
29
|
+
xml_reader :identifier, :from => '@id'
|
30
|
+
|
31
|
+
def identifier=(new_id)
|
32
|
+
@identifier = Mexico::Util::to_xml_id(new_id)
|
33
|
+
end
|
34
|
+
|
30
35
|
xml_accessor :name, :from => '@name'
|
31
36
|
|
32
37
|
xml_accessor :unit, :from => '@unit'
|
@@ -25,8 +25,12 @@
|
|
25
25
|
class Mexico::FileSystem::Section
|
26
26
|
|
27
27
|
LIFECYCLE = 'lifecycle'
|
28
|
-
|
29
28
|
VOCABULARIES = 'vocabularies'
|
29
|
+
LAYER_TYPES = 'layerTypes'
|
30
|
+
MEDIA_CONTEXT = 'mediaContext'
|
31
|
+
DATA_MODEL = 'dataModel'
|
32
|
+
|
33
|
+
SECTION_KEYS = [LIFECYCLE, VOCABULARIES, LAYER_TYPES, MEDIA_CONTEXT, DATA_MODEL]
|
30
34
|
|
31
35
|
include ::ROXML
|
32
36
|
xml_name 'Section'
|
@@ -36,6 +40,28 @@ class Mexico::FileSystem::Section
|
|
36
40
|
xml_accessor :properties, :as => [::Mexico::FileSystem::Property], :from => "Property"
|
37
41
|
xml_accessor :property_maps, :as => [::Mexico::FileSystem::PropertyMap], :from => "PropertyMap"
|
38
42
|
|
43
|
+
def initialize(key='NOTGIVEN')
|
44
|
+
@key = key
|
45
|
+
@properties = []
|
46
|
+
@property_maps = []
|
47
|
+
end
|
48
|
+
|
49
|
+
def has_key?(p_key)
|
50
|
+
# compare_list(p_key)
|
51
|
+
return true if properties.any?{|x| x.key.to_sym == p_key.to_sym}
|
52
|
+
return true if property_maps.any?{|x| x.key.to_sym == p_key.to_sym}
|
53
|
+
false
|
54
|
+
end
|
39
55
|
|
56
|
+
def [](p_key)
|
57
|
+
# compare_list(p_key)
|
58
|
+
if properties.any?{|x| x.key.to_sym == p_key.to_sym}
|
59
|
+
return properties.find{|x| x.key.to_sym == p_key.to_sym}
|
60
|
+
end
|
61
|
+
if property_maps.any?{|x| x.key.to_sym == p_key.to_sym}
|
62
|
+
return property_maps.find{|x| x.key.to_sym == p_key.to_sym}
|
63
|
+
end
|
64
|
+
return nil
|
65
|
+
end
|
40
66
|
|
41
67
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
class Mexico::Util::FancyWriter
|
4
|
+
|
5
|
+
attr_reader :stream
|
6
|
+
attr_reader :prefix_stack
|
7
|
+
|
8
|
+
def initialize(p_stream, &block)
|
9
|
+
@stream = p_stream
|
10
|
+
@prefix_stack = []
|
11
|
+
if block_given?
|
12
|
+
instance_eval &block
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def prepend(prepend_string=' ', &block)
|
17
|
+
@prefix_stack << prepend_string
|
18
|
+
instance_eval &block
|
19
|
+
@prefix_stack.pop
|
20
|
+
end
|
21
|
+
|
22
|
+
def comment(comment_string='# ', &block)
|
23
|
+
if block_given?
|
24
|
+
prepend(comment_string, &block)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def indent(number=2, &block)
|
29
|
+
prepend(' '*number, &block)
|
30
|
+
end
|
31
|
+
|
32
|
+
def tab_indent(number=2, &block)
|
33
|
+
prepend("\t"*number, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def write(*line)
|
37
|
+
lines = line
|
38
|
+
lines = [''] if lines == []
|
39
|
+
lines.each do |l|
|
40
|
+
stream << "%s%s%s" %[@prefix_stack.join(''),l,"\n"]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
alias :w :write
|
45
|
+
alias :<< :write
|
46
|
+
alias :line :write
|
47
|
+
end
|
data/lib/mexico/util.rb
CHANGED
@@ -39,13 +39,16 @@ module Mexico::Util
|
|
39
39
|
# @param string [String] The string to be converted to an ID.
|
40
40
|
# @return [String] The resulting ID.
|
41
41
|
def self.to_xml_id(string)
|
42
|
+
return nil if string.nil? # @todo auto-assign IDs
|
42
43
|
result = string.downcase
|
43
44
|
UMLAUTS.each_pair do |u,v|
|
44
45
|
result.gsub!(/#{u}/, v)
|
45
46
|
end
|
46
|
-
|
47
|
+
result.gsub!(/[^\w\d]/, '_')
|
48
|
+
return result.gsub(/_+/, '_')
|
47
49
|
end
|
48
50
|
|
49
51
|
end
|
50
52
|
|
51
|
-
require 'mexico/util/fancy_container'
|
53
|
+
require 'mexico/util/fancy_container'
|
54
|
+
require 'mexico/util/fancy_writer'
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# This file is part of the MExiCo gem.
|
2
|
+
# Copyright (c) 2012-2014 Peter Menke, SFB 673, Universität Bielefeld
|
3
|
+
# http://www.sfb673.org
|
4
|
+
#
|
5
|
+
# MExiCo is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU Lesser General Public License as
|
7
|
+
# published by the Free Software Foundation, either version 3 of
|
8
|
+
# the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# MExiCo is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
16
|
+
# License along with MExiCo. If not, see
|
17
|
+
# <http://www.gnu.org/licenses/>.
|
18
|
+
|
19
|
+
require 'spec_helper'
|
20
|
+
|
21
|
+
describe Mexico::Util::FancyWriter do
|
22
|
+
|
23
|
+
|
24
|
+
# set up an initial corpus representation from the example file
|
25
|
+
before(:each) do
|
26
|
+
@string = String.new
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'FancyWriter' do
|
31
|
+
|
32
|
+
it 'should write lines without method as they are' do
|
33
|
+
@writer = Mexico::Util::FancyWriter.new(@string) do
|
34
|
+
w "Foo"
|
35
|
+
end
|
36
|
+
@string.should eq "Foo\n"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should write comments without options as '# '" do
|
40
|
+
@writer = Mexico::Util::FancyWriter.new(@string) do
|
41
|
+
comment do
|
42
|
+
w "Foo"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
@string.should eq "# Foo\n"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should write comments with options correctly" do
|
49
|
+
@writer = Mexico::Util::FancyWriter.new(@string) do
|
50
|
+
comment '// ' do
|
51
|
+
w "Foo"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
@string.should eq "// Foo\n"
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should export a complex example correctly." do
|
58
|
+
@writer = Mexico::Util::FancyWriter.new(@string) do
|
59
|
+
comment '# ' do
|
60
|
+
line 'This is an example.'
|
61
|
+
line 'This should be a block at the top.'
|
62
|
+
end
|
63
|
+
line 'config:'
|
64
|
+
indent 4 do
|
65
|
+
line 'setting:'
|
66
|
+
indent 4 do
|
67
|
+
line 'key: value.'
|
68
|
+
comment do
|
69
|
+
line 'This is an inside comment.'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
puts @string
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/spec/fiesta/elan_spec.rb
CHANGED
@@ -30,14 +30,47 @@ describe Mexico::Fiesta::Interfaces::ElanInterface do
|
|
30
30
|
context 'Elan ' do
|
31
31
|
it 'reads data from a test file' do
|
32
32
|
path = File.join @assetspath, 'fiesta', 'elan'
|
33
|
-
filename = File.join path, 'ElanFileFormat.eaf'
|
33
|
+
filename = File.join path, 'Trial04.eaf' #'ElanFileFormat.eaf'
|
34
34
|
@fdoc = ::Mexico::Fiesta::Interfaces::ElanInterface.import(File.open(filename))
|
35
35
|
File.open(File.join(path,'test.out.fst'),'w') do |f|
|
36
36
|
f << @fdoc.to_xml
|
37
37
|
end
|
38
38
|
end
|
39
|
+
|
40
|
+
it 'reads data from the all-formats file' do
|
41
|
+
path = File.join @assetspath, 'fiesta', 'elan'
|
42
|
+
filename = File.join path, 'ElanFileFormat.eaf' #'ElanFileFormat.eaf'
|
43
|
+
@fdoc = ::Mexico::Fiesta::Interfaces::ElanInterface.import(File.open(filename))
|
44
|
+
File.open(File.join(path,'ElanFileFormat.fst'),'w') do |f|
|
45
|
+
f << @fdoc.to_xml
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'exports a FiESTA file to EAF' do
|
50
|
+
@fdoc = ::Mexico::FileSystem::FiestaDocument.open(File.join(@assetspath, 'fiesta', 'elan', 'test.out.fst')) # Fiesta::Interfaces::ElanInterface.import(File.open(filename))
|
51
|
+
@fdoc.should_not be nil
|
52
|
+
File.open(File.join(@assetspath, 'fiesta', 'elan', 'test.out.eaf'),'w') do |f|
|
53
|
+
::Mexico::Fiesta::Interfaces::ElanInterface::export(@fdoc, f)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'imports and exports an EAF document and preserves its structure and contents' do
|
58
|
+
path = File.join @assetspath, 'fiesta', 'elan'
|
59
|
+
filename = File.join path, 'Trial04.eaf'
|
60
|
+
@fdoc = ::Mexico::Fiesta::Interfaces::ElanInterface.import(File.open(filename))
|
61
|
+
# ::Mexico::FileSystem::FiestaDocument.open(File.join(@assetspath, 'fiesta', 'elan', 'test.out.fst')) # Fiesta::Interfaces::ElanInterface.import(File.open(filename))
|
62
|
+
@fdoc.should_not be nil
|
63
|
+
File.open(File.join(@assetspath, 'fiesta', 'elan', 'Trial04.fst'),'w') do |f|
|
64
|
+
f << @fdoc.to_xml
|
65
|
+
end
|
66
|
+
File.open(File.join(@assetspath, 'fiesta', 'elan', 'Trial04.OUT.eaf'),'w') do |f|
|
67
|
+
::Mexico::Fiesta::Interfaces::ElanInterface::export(@fdoc, f)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
|
39
72
|
end
|
40
73
|
end
|
41
74
|
end
|
42
75
|
|
43
|
-
end
|
76
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# This file is part of the MExiCo gem.
|
2
|
+
# Copyright (c) 2012-2014 Peter Menke, SFB 673, Universität Bielefeld
|
3
|
+
# http://www.sfb673.org
|
4
|
+
#
|
5
|
+
# MExiCo is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU Lesser General Public License as
|
7
|
+
# published by the Free Software Foundation, either version 3 of
|
8
|
+
# the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# MExiCo is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
16
|
+
# License along with MExiCo. If not, see
|
17
|
+
# <http://www.gnu.org/licenses/>.
|
18
|
+
|
19
|
+
require 'spec_helper'
|
20
|
+
|
21
|
+
describe Mexico::FileSystem::Layer do
|
22
|
+
|
23
|
+
before(:each) do
|
24
|
+
@basepath = File.join File.dirname(__FILE__), '..', '..'
|
25
|
+
@path = File.join @basepath, 'assets', 'fiesta', 'props'
|
26
|
+
@filename = File.join(@path,'props.fst')
|
27
|
+
@fdoc = ::Mexico::FileSystem::FiestaDocument.open(@filename)
|
28
|
+
|
29
|
+
@outfile = File.join(@path,'out.fst')
|
30
|
+
File.open(@outfile, 'w') do |f|
|
31
|
+
f.write @fdoc.to_xml
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'Fiesta ' do
|
36
|
+
context 'Layer' do
|
37
|
+
it 'reads props from layers' do
|
38
|
+
@fdoc.layers.first.should respond_to(:properties)
|
39
|
+
@fdoc.layers.first.properties.should have_key('elanTierType')
|
40
|
+
@fdoc.layers.first.properties['elanTierType'].should_not be nil
|
41
|
+
@fdoc.layers.first.properties['elanTierType'].value.should eq 'TIME_SUBDIVISION'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/spec/fiesta/praat_spec.rb
CHANGED
@@ -47,6 +47,25 @@ describe Mexico::Fiesta::Interfaces::ShortTextGridInterface do
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
+
|
51
|
+
it 'writes data to a short text grid file' do
|
52
|
+
path = File.join @assetspath, 'fiesta', 'praat'
|
53
|
+
filename = File.join path, 'mexico.ShortTextGrid'
|
54
|
+
@fdoc = ::Mexico::Fiesta::Interfaces::ShortTextGridInterface.import(File.open(filename))
|
55
|
+
|
56
|
+
@outfile = File.join path, 'mexico.OUT.ShortTextGrid'
|
57
|
+
::Mexico::Fiesta::Interfaces::ShortTextGridInterface.export(@fdoc, File.open(@outfile, 'w'))
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'writes data to a text grid file' do
|
61
|
+
path = File.join @assetspath, 'fiesta', 'praat'
|
62
|
+
filename = File.join path, 'mexico.TextGrid'
|
63
|
+
@fdoc = ::Mexico::Fiesta::Interfaces::TextGridInterface.import(File.open(filename))
|
64
|
+
|
65
|
+
@outfile = File.join path, 'mexico.OUT.TextGrid'
|
66
|
+
::Mexico::Fiesta::Interfaces::TextGridInterface.export(@fdoc, File.open(@outfile, 'w'))
|
67
|
+
end
|
68
|
+
|
50
69
|
end
|
51
70
|
end
|
52
71
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mexico
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Menke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -236,6 +236,7 @@ files:
|
|
236
236
|
- assets/fiesta/head/head.fst
|
237
237
|
- assets/fiesta/praat/mexico.ShortTextGrid
|
238
238
|
- assets/fiesta/praat/mexico.TextGrid
|
239
|
+
- assets/fiesta/props/props.fst
|
239
240
|
- assets/helpers/collection_ref_handler.rb
|
240
241
|
- assets/helpers/id_ref_handler.rb
|
241
242
|
- assets/helpers/roxml_attribute_handler.rb
|
@@ -247,6 +248,7 @@ files:
|
|
247
248
|
- features/support/env.rb
|
248
249
|
- info/releasenotes/0.0.1.md
|
249
250
|
- info/releasenotes/0.0.10.md
|
251
|
+
- info/releasenotes/0.0.11.md
|
250
252
|
- info/releasenotes/0.0.2.md
|
251
253
|
- info/releasenotes/0.0.3.md
|
252
254
|
- info/releasenotes/0.0.4.md
|
@@ -306,11 +308,14 @@ files:
|
|
306
308
|
- lib/mexico/not_yet_implemented_error.rb
|
307
309
|
- lib/mexico/util.rb
|
308
310
|
- lib/mexico/util/fancy_container.rb
|
311
|
+
- lib/mexico/util/fancy_writer.rb
|
309
312
|
- spec/constraints/constraints_spec.rb
|
313
|
+
- spec/core/fancy_writer_spec.rb
|
310
314
|
- spec/core/media_type_spec.rb
|
311
315
|
- spec/fiesta/b6_spec.rb
|
312
316
|
- spec/fiesta/elan_spec.rb
|
313
317
|
- spec/fiesta/head_spec.rb
|
318
|
+
- spec/fiesta/layer_prop_spec.rb
|
314
319
|
- spec/fiesta/praat_spec.rb
|
315
320
|
- spec/fiesta/read_spec.rb
|
316
321
|
- spec/file_system_based/better_collection_spec.rb
|