mexico 0.0.10 → 0.0.11
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.
- 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
|