vecxoz commited on
Commit
61c8ddd
·
verified ·
1 Parent(s): 1baf376

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. SCTK/src/acomp/acomp.pl +328 -0
  2. SCTK/src/acomp/makefile +27 -0
  3. SCTK/src/acomp/makefile.in +27 -0
  4. SCTK/src/align2html/Segment.pm +325 -0
  5. SCTK/src/align2html/SegmentGroup.pm +407 -0
  6. SCTK/src/align2html/Token.pm +166 -0
  7. SCTK/src/align2html/align2html-main.pl +1436 -0
  8. SCTK/src/align2html/align2html.pl +0 -0
  9. SCTK/src/align2html/buildInstallVersion.pl +69 -0
  10. SCTK/src/align2html/buildPack.pl +29 -0
  11. SCTK/src/align2html/makefile +25 -0
  12. SCTK/src/align2html/makefile.in +25 -0
  13. SCTK/src/align2html/packImageTarFile +229 -0
  14. SCTK/src/chfilt/chfilt.pl +1042 -0
  15. SCTK/src/chfilt/makefile +40 -0
  16. SCTK/src/chfilt/makefile.in +40 -0
  17. SCTK/src/ctmValidator/makefile +19 -0
  18. SCTK/src/hamzaNorm/hamzaNorm.pl +95 -0
  19. SCTK/src/hamzaNorm/makefile +33 -0
  20. SCTK/src/hamzaNorm/makefile.in +33 -0
  21. SCTK/src/rttmValidator/makefile +19 -0
  22. SCTK/src/rttmValidator/makefile.in +19 -0
  23. SCTK/src/rttmValidator/rttmValidator.pl +917 -0
  24. SCTK/src/sclite/addarc1.o +0 -0
  25. SCTK/src/sclite/alex.h +23 -0
  26. SCTK/src/sclite/align.c +1443 -0
  27. SCTK/src/sclite/align.o +0 -0
  28. SCTK/src/sclite/anovar.c +485 -0
  29. SCTK/src/sclite/arcseq1.c +13 -0
  30. SCTK/src/sclite/arcseq1.o +0 -0
  31. SCTK/src/sclite/config.in +151 -0
  32. SCTK/src/sclite/ctm2ctm.c +518 -0
  33. SCTK/src/sclite/killarc1.o +0 -0
  34. SCTK/src/sclite/llist.c +159 -0
  35. SCTK/src/sclite/llist.h +32 -0
  36. SCTK/src/sclite/makefile.in +246 -0
  37. SCTK/src/sclite/marc1.c +25 -0
  38. SCTK/src/sclite/mcnemar.c +18 -0
  39. SCTK/src/sclite/mfa.c +299 -0
  40. SCTK/src/sclite/mnode1.c +55 -0
  41. SCTK/src/sclite/mtchprs.c +833 -0
  42. SCTK/src/sclite/net_adt.o +0 -0
  43. SCTK/src/sclite/order.c +277 -0
  44. SCTK/src/sclite/order.o +0 -0
  45. SCTK/src/sclite/pad.h +7 -0
  46. SCTK/src/sclite/sclite.c +764 -0
  47. SCTK/src/sclite/signtest.c +304 -0
  48. SCTK/src/sclite/slm_intf.c +195 -0
  49. SCTK/src/sclite/statdist.o +0 -0
  50. SCTK/src/sclite/stm.h +31 -0
SCTK/src/acomp/acomp.pl ADDED
@@ -0,0 +1,328 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/perl -w
2
+
3
+ my $Version="1.1";
4
+
5
+ #####
6
+ # Version 1.0 Released September 9, 1997
7
+ # - Initial Release
8
+ # Version 1.1 Released October 24, 1997
9
+ # - added the -f flag to interpret fragments
10
+
11
+
12
+ my $Usage="Usage: acompl.pl [ -t -s -f ] [ -i fmt ] -m min -l lex Infile|- OutFile|-\n".
13
+ "Version: $Version\n".
14
+ "Desc: The 'acomp' program expands compound words in German orthography into\n".
15
+ " the constituent parts of those compound words. The program uses the\n".
16
+ " LDC German Lexicon as a basis for the expansions. Input is read from\n".
17
+ " InFile or STDIN if infile is '-' and output is written to Outfile or\n".
18
+ " STDOUT if OutFile is '-'\n".
19
+ "Options:\n".
20
+ " -m min Set the minimum length on a compound costituent part to 'min'.\n".
21
+ " Default is 2.\n".
22
+ " -l lex File name of the LDC German Dictionary\n".
23
+ " -t Disable the processing of triplet consonants\n".
24
+ " -s Disable the processing of -s and -en insertions\n".
25
+ " -f Divide word fragments as best as you can\n".
26
+ " -i fmt Set the input file formant to 'fmt'. The possible choices are:\n".
27
+ " txt -> plain text, the default\n".
28
+ " ctm -> CTM format, ignores all but the 5th column, and if\n".
29
+ " a division occurs and a confidence score is present,\n".
30
+ " the confidence score is copied to all parts.\n".
31
+ " stm -> STM format, change only the text field of the stm record\n".
32
+ "\n";
33
+ $Lex = "";
34
+ $MaxLen = 0;
35
+ %LexHash = ();
36
+ %CompHash = ();
37
+ $MinCompLen = 2;
38
+ $DoTriplet = 1;
39
+ $DoInserts = 1;
40
+ $InFmt = "txt";
41
+ $InFile = "";
42
+ $OutFile = "";
43
+ $Frag = 0;
44
+
45
+ $| = 1; # This will cause stdout to be flushed whenever we print to it.
46
+
47
+ use Getopt::Long;
48
+ my $ret = GetOptions ("l=s",
49
+ "m=s",
50
+ "t",
51
+ "s",
52
+ "i:s",
53
+ "f");
54
+ die "\n$Usage\nError: Failed to parse arguments" if (! $ret);
55
+
56
+
57
+ if (defined($opt_l)) { $Lex = $opt_l; } else { die("$Usage\n\nError: Lexicon required via -l.\n"); }
58
+ if (defined($opt_m)) { $MinCompLen = $opt_m; }
59
+ if (defined($opt_t)) { $DoTriplet = 0; $opt_t = 0;}
60
+ if (defined($opt_s)) { $DoInserts = 0; $opt_s = 0;}
61
+ if (defined($opt_f)) { $Frag = 1; $opt_f = 0;}
62
+ if (defined($opt_i)) {
63
+ die("$Usage\n\nError: Undefined input format '$opt_i'")
64
+ if ($opt_i !~ /^(txt|ctm|stm)$/);
65
+ $InFmt = $opt_i;
66
+ }
67
+ #### The main functions arguments:
68
+ if ($#ARGV > 1) { print "\n$Usage\nToo many arguments\n\n"; exit 1; }
69
+ if ($#ARGV == 0) { print "\n$Usage\nOutput Not Specified\n\n"; exit 1; }
70
+ if ($#ARGV == -1) { print "\n$Usage\nInput and Output Not Specified\n\n";
71
+ exit 1; }
72
+
73
+ $InFile=$ARGV[0];
74
+ $OutFile=$ARGV[1];
75
+ die("$Usage\nError: Input file $InFile does not exist\n")
76
+ if ($InFile ne "-" && ! -r $InFile);
77
+
78
+ ########################## MAIN #####################D
79
+
80
+ &LoadLex();
81
+
82
+ open(IN,"$InFile") || die("Error: Unable to open input file '$InFile'");
83
+ open(OUT,">$OutFile") || die("Error: Unable to open output file '$OutFile'");
84
+
85
+ while (<IN>){
86
+ chop;
87
+ if ($_ =~ /^;;/){
88
+ print OUT "$_\n";
89
+ } elsif ($InFmt eq "txt"){
90
+ print OUT &String_LU($_)."\n";
91
+ } elsif ($InFmt eq "ctm"){
92
+ s/^\s+//;
93
+ local(@ctm);
94
+ local(@new_words);
95
+ local($i);
96
+ local($newt);
97
+ local($conf);
98
+
99
+ @ctm = split(/\s+/,$_);
100
+ if ($#ctm <= 4) { $conf = "" ; } else { $conf = $ctm[5]; }
101
+
102
+ $newt = &String_LU($ctm[4]);
103
+ @new_words = split(/\s+/,$newt);
104
+ for ($i=0; $i<=$#new_words; $i++){
105
+ printf OUT ("%s %s %.2f %.2f %s %s\n",$ctm[0],$ctm[1],
106
+ $ctm[2] + ($i * ($ctm[3] / ($#new_words+1))),
107
+ $ctm[3] / ($#new_words + 1), $new_words[$i], $conf);
108
+ }
109
+ } elsif ($InFmt eq "stm"){
110
+ s/^\s+//;
111
+ local(@sl) = split(/\s+/,$_,7);
112
+ local($txt);
113
+ die "Error: Not enough fields in stm line '$_'\n" if ($#sl < 4);
114
+
115
+ if ($#sl == 4){
116
+ print OUT "$sl[0] $sl[1] $sl[2] $sl[3] $sl[4]\n";
117
+ } else {
118
+ print OUT "$sl[0] $sl[1] $sl[2] $sl[3] $sl[4]";
119
+ if ($sl[5] =~ /^<.*>$/){
120
+ print OUT " $sl[5]";
121
+ $txt = "";
122
+ if ($#sl == 6){ $txt = $sl[6]; }
123
+ } else {
124
+ $txt = $sl[5];
125
+ if ($#sl == 6){ $txt .= " ".$sl[6]; }
126
+ }
127
+ if ($txt ne ""){
128
+ print OUT " ".&String_LU($txt);
129
+ }
130
+ print OUT "\n";
131
+ }
132
+ }
133
+ }
134
+
135
+ close (IN); close(OUT);
136
+
137
+ ################# END OF MAIN #########################
138
+ ###########################################################
139
+
140
+ sub String_LU{
141
+ local($s) = @_;
142
+ local($new) = "";
143
+ local($ne);
144
+ $s =~ tr/a-z/A-Z/;
145
+ $s =~ tr/\340-\377/\300-\337/;
146
+ foreach $word(split(/\s+/,$s)){
147
+ if ($word =~ /^\(.*\)$/){
148
+ $word =~ s/^\((.*)\)$/$1/;
149
+ local($lookup) = &Comp_LU($word);
150
+ if ($word !~ /-$/ || (! $Frag)){
151
+ foreach $ne(split(/\s+/,$lookup)){
152
+ $new .= "(".$ne.") ";
153
+ }
154
+ } else {
155
+ $lookup =~ s/(\S+-)$/aq($1)/;
156
+ $new .= "$lookup ";
157
+ }
158
+ } else {
159
+ $new .= &Comp_LU($word)." ";
160
+ }
161
+ }
162
+ $new =~ s/ $//;
163
+ $new;
164
+ }
165
+
166
+ sub Comp_LU{
167
+ local($text) = @_;
168
+ local(@Comps) = ();
169
+ local($comp);
170
+ local($db) = 0;
171
+
172
+ if ($CompHash{$text} !~ /^$/){
173
+ print "hashed $text = $CompHash{$text}\n" if ($db);
174
+ $CompHash{$text};
175
+ } else {
176
+ if ($Frag && $text =~ /-$/) {
177
+ print "Fragment Lookup '$text'\n" if ($db);
178
+
179
+ local($len) = length($text);
180
+ local($htext) = "";
181
+ local($nocomp) = 1;
182
+ local($i, $j);
183
+ for ($i=$len-2; $i>=$MinCompLen && $nocomp; $i--){
184
+ $htext = substr($text,0,$i);
185
+ &is_Compound("",$htext,"",*Comps);
186
+ if ($#Comps != -1){
187
+ print "Fragment match @Comps\n" if ($db);
188
+ foreach ($j=0; $j <= $#Comps; $j++){
189
+ $Comps[$j] .= " ".substr($text,$i);
190
+ }
191
+ $nocomp = 0;
192
+ }
193
+ }
194
+ } else {
195
+ print "compute $text " if ($db);
196
+ &is_Compound("",$text,"",*Comps);
197
+ }
198
+
199
+ if ($#Comps == -1) {
200
+ $comp = $text;
201
+ } elsif ($#Comps > 0) {
202
+ $comp = "{";
203
+ foreach $c (@Comps){
204
+ $comp .= " $c /";
205
+ }
206
+ $comp =~ s:/$:}:;
207
+ } else {
208
+ $comp = $Comps[0];
209
+ }
210
+ $CompHash{$text} = $comp;
211
+ print "compute $text = $comp\n" if ($db);
212
+ $comp;
213
+ }
214
+ }
215
+
216
+ sub is_Compound{
217
+ local($hist,$val,$ind,*comps) = @_;
218
+ local($sval);
219
+ local($resid);
220
+ local($vallen) = length($val);
221
+ local($srchlen) = $MaxLen;
222
+ local($db) = 0;
223
+ local($stop_recur) = 0;
224
+ local($i);
225
+
226
+ $srchlen = $vallen if ($vallen < $MaxLen);
227
+
228
+ printf $ind."is_Compound hist: '$hist' val: '$val' slen: $srchlen\n" if ($db);
229
+ if ($LexHash{$val} eq "1"){
230
+ ### The word is already in the hashed list, return it.
231
+ local($co);
232
+ ($co = "$hist $val") =~ s/^ //;
233
+ print "$ind******* SUCCESS Search value pre-defined '$co'\n" if ($db);
234
+ push(@comps,$co);
235
+ 1;
236
+ } else {
237
+ ### loop through all of the characters in a
238
+ for ($i=$srchlen; $i>=$MinCompLen && ! $stop_recur; $i--){
239
+ $sval = substr($val,0,$i);
240
+ print $ind." $sval\n" if ($db);
241
+ if ($LexHash{$sval} eq "1"){
242
+ $resid = substr($val,$i);
243
+ print $ind." Possible subword '$sval' residual '$resid'\n" if ($db);
244
+ if (length($resid) >= $MinCompLen){
245
+ if (&is_Compound($hist." $sval",$resid, $ind." |",*comps) == 1){
246
+ $stop_recur = 1;
247
+ print "$ind**** Curtailing search for normal lookup\n" if ($db);
248
+ } else {
249
+ print "$ind**** Failed to Curtail search\n" if ($db);
250
+ }
251
+ } else {
252
+ print "$ind**** Residual length < MinCompLen $MinCompLen\n" if ($db);
253
+ }
254
+ #### handle the geminate constant conditional
255
+ if (! $stop_recur && $DoTriplet && $sval =~ /([bcdfghjklmnpqrstvwxyz])\1$/){
256
+ $resid = substr($val,$i-1);
257
+ print $ind." Possible geminate consonate subword residual $resid\n" if ($db);
258
+ if (length($resid) >= $MinCompLen){
259
+ if (&is_Compound($hist." $sval",$resid, $ind." |",*comps) == 1){
260
+ $stop_recur = 1;
261
+ print "$ind**** Curtailing search for triplet consonants\n" if ($db);
262
+ } else {
263
+ print "$ind**** Failed to Curtail search\n" if ($db);
264
+ }
265
+ }
266
+ }
267
+ #### handle the insertion of syllables
268
+ if (! $stop_recur && $DoInserts && ( $resid =~ /^([sS]|[eE][nN])/ ) ){
269
+ local($gen);
270
+ if ($resid =~ /^[sS]/){ $resid = substr($val,$i+1); $gen = "s" }
271
+ if ($resid =~ /^[eE][nN]/){ $resid = substr($val,$i+2); $gen = "en" }
272
+ print $ind." Possible additional '$gen' on residual '$gen'$resid\n" if ($db);
273
+ if (length($resid) >= $MinCompLen){
274
+ if (&is_Compound($hist." $sval",$resid, $ind." |",*comps) == 1){
275
+ $stop_recur = 1;
276
+ print "$ind**** Curtailing search for insertion of syllables\n" if ($db);
277
+ } else {
278
+ print "$ind**** Failed to Curtail search\n" if ($db);
279
+ }
280
+ }
281
+ }
282
+ }
283
+ }
284
+ $stop_recur;
285
+ }
286
+ }
287
+
288
+ sub LoadLex{
289
+ local($len);
290
+ local($db) = 0;
291
+ open(LEX,$Lex) || die("Unable to open Lexicon '$Lex'");
292
+
293
+ print "Reading Lexicon: '$Lex'\n Each . is 10000 entries: " if ($db);
294
+ while (<LEX>){
295
+ chop;
296
+ ($word) = split;
297
+ $word =~ tr/a-z/A-Z/;
298
+ $word =~ tr/\340-\377/\300-\337/;
299
+
300
+ if ($word =~ /[-_]/){
301
+ ($sep = $word) =~ s/[-_]+/ /g;
302
+ ($cmp = $word) =~ s/_//g;
303
+ foreach $sw(split(/\s+/,$sep)){
304
+ $LexHash{$sw} = "1";
305
+ $len = length($sw);
306
+ $MaxLen = $len if ($MaxLen < $len);
307
+ }
308
+ $CompHash{$cmp} = $sep;
309
+ if ($cmp =~ /-/){
310
+ $cmp =~ s/-//g;
311
+ $CompHash{$cmp} = $sep;
312
+ }
313
+ } else {
314
+ $LexHash{$word} = "1";
315
+ $CompHash{$word} = $word;
316
+ }
317
+ if (($. + 1) % 10000 == 0){
318
+ print "." if ($db);
319
+ }
320
+ }
321
+ print "\n $. entries loaded, Largest word is $MaxLen\n" if ($db);
322
+
323
+ close(LEX);
324
+
325
+ # print "LexHash:\n"; foreach $key(sort(keys %LexHash)) { print " $key -> $LexHash{$key}\n"; }
326
+ # print "CompHash:\n"; foreach $key(sort(keys %CompHash)) { print " $key -> $CompHash{$key}\n"; }
327
+ }
328
+
SCTK/src/acomp/makefile ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # **********************************************************
2
+ # Makefile for rfilter1 Directory
3
+ # **********************************************************
4
+ SHELL = /bin/sh
5
+ PREFIX=/home/userube/mozilla/zz__temp_5_rover/SCTK
6
+ bindir = $(PREFIX)/bin
7
+ T=../test_suite
8
+ PERL=/slp/sware/Linux/bin/perl
9
+
10
+ all: acomp.pl
11
+
12
+ acomp.pl:
13
+ chmod +x acomp.pl
14
+
15
+ setTests:
16
+
17
+ check: all
18
+ @echo "Testing acomp.pl"
19
+ @echo " No tests defined for acomp.pl"
20
+
21
+ install: all
22
+ cp acomp.pl $(DESTDIR)$(bindir)
23
+
24
+ clean:
25
+
26
+ distclean: clean
27
+ $(RM) -r *~ makefile
SCTK/src/acomp/makefile.in ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # **********************************************************
2
+ # Makefile for rfilter1 Directory
3
+ # **********************************************************
4
+ SHELL = /bin/sh
5
+ PREFIX=
6
+ bindir = $(PREFIX)/bin
7
+ T=../test_suite
8
+ PERL=/slp/sware/Linux/bin/perl
9
+
10
+ all: acomp.pl
11
+
12
+ acomp.pl:
13
+ chmod +x acomp.pl
14
+
15
+ setTests:
16
+
17
+ check: all
18
+ @echo "Testing acomp.pl"
19
+ @echo " No tests defined for acomp.pl"
20
+
21
+ install: all
22
+ cp acomp.pl $(DESTDIR)$(bindir)
23
+
24
+ clean:
25
+
26
+ distclean: clean
27
+ $(RM) -r *~ makefile
SCTK/src/align2html/Segment.pm ADDED
@@ -0,0 +1,325 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ALIGN2HTML
2
+ # Author: Jerome Ajot
3
+ #
4
+ # This software was developed at the National Institute of Standards and Technology by
5
+ # employees of the Federal Government in the course of their official duties. Pursuant
6
+ # to title 17 Section 105 of the United States Code this software is not subject to
7
+ # copyright protection and is in the public domain. ALIGN2HTML is an experimental system.
8
+ # NIST assumes no responsibility whatsoever for its use by other parties, and makes no
9
+ # guarantees, expressed or implied, about its quality, reliability, or any other
10
+ # characteristic. We would appreciate acknowledgement if the software is used.
11
+ #
12
+ # THIS SOFTWARE IS PROVIDED "AS IS." With regard to this software, NIST MAKES NO EXPRESS
13
+ # OR IMPLIED WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING MERCHANTABILITY,
14
+ # OR FITNESS FOR A PARTICULAR PURPOSE.
15
+
16
+ package Segment;
17
+ use strict;
18
+ use Data::Dumper;
19
+
20
+ use Token;
21
+
22
+ sub new
23
+ {
24
+ my $class = shift;
25
+ my $self = {};
26
+
27
+ $self->{ID} = shift;
28
+ $self->{SPKRID} = shift;
29
+ $self->{TOKENS} = {};
30
+ $self->{MINX} = 10000000;
31
+ $self->{MAXX} = 0;
32
+ $self->{HEIGHT} = 0;
33
+ $self->{HASFAKETIME} = 0;
34
+
35
+ bless $self;
36
+ return $self;
37
+ }
38
+
39
+ sub AddToken
40
+ {
41
+ my ($self, $tkn) = @_;
42
+ $self->{TOKENS}{$tkn->{ID}} = $tkn;
43
+ }
44
+
45
+ sub SetY
46
+ {
47
+ my ($self, $ypos) = @_;
48
+
49
+ foreach my $tknid(sort keys %{ $self->{TOKENS} })
50
+ {
51
+ $self->{TOKENS}{$tknid}->SetYPos($ypos);
52
+ }
53
+ }
54
+
55
+ sub isTokenInSegment
56
+ {
57
+ my ($self, $tokenid) = @_;
58
+
59
+ foreach my $tknid(sort keys %{ $self->{TOKENS} })
60
+ {
61
+ return 1 if($tknid == $tokenid);
62
+ }
63
+
64
+ return 0;
65
+ }
66
+
67
+ sub CalculateMinMaxX
68
+ {
69
+ my ($self) = @_;
70
+
71
+ foreach my $tknid(sort keys %{ $self->{TOKENS} })
72
+ {
73
+ next if( ($self->{TOKENS}{$tknid}->{XSTARTPOS} == 0) && ($self->{TOKENS}{$tknid}->{XENDPOS} == 0) && ($self->{TOKENS}{$tknid}->{TEXT} eq "") );
74
+ $self->{MINX} = $self->{TOKENS}{$tknid}->{XSTARTPOS} if($self->{MINX} > $self->{TOKENS}{$tknid}->{XSTARTPOS});
75
+ $self->{MAXX} = $self->{TOKENS}{$tknid}->{XENDPOS} if($self->{MAXX} < $self->{TOKENS}{$tknid}->{XENDPOS});
76
+ }
77
+ }
78
+
79
+ sub HasOnlyOneFakeToken
80
+ {
81
+ my ($self) = @_;
82
+
83
+ foreach my $tknid(sort keys %{ $self->{TOKENS} })
84
+ {
85
+ return 0 if( !( ($self->{TOKENS}{$tknid}->{XSTARTPOS} == 0) && ($self->{TOKENS}{$tknid}->{XENDPOS} == 0) && ($self->{TOKENS}{$tknid}->{TEXT} eq "") ) );
86
+ }
87
+
88
+ return 1;
89
+ }
90
+
91
+ sub CleanSegmentPrevNext
92
+ {
93
+ my ($self) = @_;
94
+
95
+ foreach my $tknid(sort keys %{ $self->{TOKENS} })
96
+ {
97
+ my $myToken = $self->{TOKENS}{$tknid};
98
+
99
+ for(my $i=0; $i< @{ $myToken->{PREVTKNID} }; $i++)
100
+ {
101
+ delete $myToken->{PREVTKNID}[$i] if(!$self->isTokenInSegment($myToken->{PREVTKNID}[$i]));
102
+ }
103
+
104
+ for(my $i=0; $i< @{ $myToken->{NEXTTKNID} }; $i++)
105
+ {
106
+ delete $myToken->{NEXTTKNID}[$i] if(!$self->isTokenInSegment($myToken->{NEXTTKNID}[$i]));
107
+ }
108
+
109
+ $myToken->{NUMPREV} = scalar( @{ $myToken->{PREVTKNID} } );
110
+ $myToken->{NUMNEXT} = scalar( @{ $myToken->{NEXTTKNID} } );
111
+ }
112
+ }
113
+
114
+ sub MultiGraphXY
115
+ {
116
+ my ($self) = @_;
117
+
118
+ my $maxheigh = 0;
119
+
120
+ if(scalar(keys %{ $self->{TOKENS} }) != 0)
121
+ {
122
+ my %tokenPositions;
123
+ my @listTokenID;
124
+ my $currentlevel = 0;
125
+ my $maxlengh = 0;
126
+
127
+ foreach my $tknid(sort {$a <=> $b} keys %{ $self->{TOKENS} })
128
+ {
129
+ $tokenPositions{$tknid}{XB} = 0;
130
+ $tokenPositions{$tknid}{XE} = 1;
131
+ $tokenPositions{$tknid}{Y} = 0;
132
+ $tokenPositions{$tknid}{TEXT} = $self->{TOKENS}{$tknid}->{TEXT};
133
+
134
+ push(@listTokenID, $tknid);
135
+
136
+ if( scalar(@{ $self->{TOKENS}{$tknid}->{PREVTKNID} }) == 0 )
137
+ {
138
+ $tokenPositions{$tknid}{Y} = $currentlevel;
139
+ $currentlevel++;
140
+ }
141
+ }
142
+
143
+ for(my $i=0; $i<@listTokenID; $i++)
144
+ {
145
+ my $tokenid = $listTokenID[$i];
146
+ my $token = $self->{TOKENS}{$tokenid};
147
+ my @prevtkn = @{ $token->{PREVTKNID} };
148
+ my @nexttkn = @{ $token->{NEXTTKNID} };
149
+
150
+ my $tokenBegin = $tokenPositions{$tokenid}{XB};
151
+ my $tokenEnd = $tokenPositions{$tokenid}{XE};
152
+ my $tokenY = $tokenPositions{$tokenid}{Y};
153
+
154
+ for(my $j=0; $j<@nexttkn; $j++)
155
+ {
156
+ my $nexttokenid = $nexttkn[$j];
157
+
158
+ my $nexttokenBegin = $tokenPositions{$nexttokenid}{XB};
159
+ my $nexttokenEnd = $tokenPositions{$nexttokenid}{XE};
160
+ my $nextTokenY = $tokenPositions{$nexttokenid}{Y};
161
+
162
+ if( $nexttokenBegin < $tokenEnd)
163
+ {
164
+ $tokenPositions{$nexttokenid}{XB} = $tokenEnd;
165
+ $tokenPositions{$nexttokenid}{XE} = $tokenPositions{$nexttokenid}{XB} + 1;
166
+ $i = -1;
167
+ }
168
+
169
+ my $nbrprev = scalar( @{ $self->{TOKENS}{$nexttokenid}->{PREVTKNID} } ) - 1;
170
+
171
+ if($nextTokenY < ($tokenY + $j - $nbrprev))
172
+ {
173
+ $tokenPositions{$nexttokenid}{Y} = $tokenY + $j - $nbrprev;
174
+ $i = -1;
175
+ }
176
+ }
177
+
178
+ for(my $j=0; $j<@prevtkn; $j++)
179
+ {
180
+ my $prevtokenid = $prevtkn[$j];
181
+
182
+ my $prevtokenBegin = $tokenPositions{$prevtokenid}{XB};
183
+ my $prevtokenEnd = $tokenPositions{$prevtokenid}{XE};
184
+
185
+ if( $prevtokenEnd != $tokenBegin)
186
+ {
187
+ $tokenPositions{$prevtokenid}{XE} = $tokenBegin;
188
+ $i = -1;
189
+ }
190
+ }
191
+ }
192
+
193
+ foreach my $tken (sort {$a <=> $b} keys %tokenPositions)
194
+ {
195
+ $maxheigh = $tokenPositions{$tken}{Y} if($tokenPositions{$tken}{Y} > $maxheigh);
196
+ $maxlengh = $tokenPositions{$tken}{XE} if($tokenPositions{$tken}{XE} > $maxlengh);
197
+ }
198
+
199
+ foreach my $tknid(sort keys %{ $self->{TOKENS} })
200
+ {
201
+ my $updown = 1;
202
+ my $base = 0;
203
+
204
+ if($self->{TOKENS}{$tknid}->{REFORSYS} eq "REF")
205
+ {
206
+ $updown = -1;
207
+ $base = $maxheigh;
208
+ }
209
+
210
+ if($self->{TOKENS}{$tknid}->{REALTIME} == 0)
211
+ {
212
+ $self->{TOKENS}{$tknid}->MakeFakeTime($tokenPositions{$tknid}{XB}, $tokenPositions{$tknid}{XE}, $maxlengh);
213
+ $self->{HASFAKETIME} = 1;
214
+ }
215
+
216
+ $self->{TOKENS}{$tknid}->{YPOS} += $base*30 + $updown*30*$tokenPositions{$tknid}{Y};
217
+ }
218
+ }
219
+
220
+ $self->{HEIGHT} = ($maxheigh+1)*30;
221
+ }
222
+
223
+ sub Compute
224
+ {
225
+ my ($self) = @_;
226
+
227
+ # Calculate Min and Max X
228
+ $self->CalculateMinMaxX();
229
+
230
+ # Clean up the previous and Next of Tokens
231
+ $self->CleanSegmentPrevNext();
232
+
233
+ # Assign X and Y for graph
234
+ $self->MultiGraphXY();
235
+ }
236
+
237
+ sub GetDraw
238
+ {
239
+ my ($self, $minx) = @_;
240
+ my $output2 = "";
241
+
242
+ my @listfirsts;
243
+ my @listlasts;
244
+
245
+ foreach my $tknid(sort keys %{ $self->{TOKENS} })
246
+ {
247
+ my @prevtkn = @{ $self->{TOKENS}{$tknid}->{PREVTKNID} };
248
+ my @nexttkn = @{ $self->{TOKENS}{$tknid}->{NEXTTKNID} };
249
+
250
+ if(scalar(@prevtkn) > 1)
251
+ {
252
+ for(my $i=1; $i<@prevtkn; $i++)
253
+ {
254
+ my $end1x = $self->{TOKENS}{$prevtkn[$i-1]}->{XENDPOS} - $minx;
255
+ my $end1y = $self->{TOKENS}{$prevtkn[$i-1]}->{YPOS};
256
+ my $end2x = $self->{TOKENS}{$prevtkn[$i]}->{XENDPOS} - $minx;
257
+ my $end2y = $self->{TOKENS}{$prevtkn[$i]}->{YPOS};
258
+
259
+ $output2 .= sprintf("jg.drawLine(scale*%.0f, %.0f, scale*%.0f, %.0f);\n", $end1x, $end1y, $end2x, $end2y);
260
+ }
261
+ }
262
+
263
+ push(@listfirsts, $tknid) if(scalar(@prevtkn) == 0);
264
+
265
+ if(scalar(@nexttkn) > 1)
266
+ {
267
+ for(my $i=1; $i<@nexttkn; $i++)
268
+ {
269
+ my $begin1x = $self->{TOKENS}{$nexttkn[$i-1]}->{XSTARTPOS} - $minx;
270
+ my $begin1y = $self->{TOKENS}{$nexttkn[$i-1]}->{YPOS};
271
+ my $begin2x = $self->{TOKENS}{$nexttkn[$i]}->{XSTARTPOS} - $minx;
272
+ my $begin2y = $self->{TOKENS}{$nexttkn[$i]}->{YPOS};
273
+
274
+ $output2 .= sprintf("jg.drawLine(scale*%.0f, %.0f, scale*%.0f, %.0f);\n", $begin1x, $begin1y, $begin2x, $begin2y);
275
+ }
276
+ }
277
+
278
+ push(@listlasts, $tknid) if(scalar(@nexttkn) == 0);
279
+ }
280
+
281
+ if(scalar(@listfirsts) > 1)
282
+ {
283
+ for(my $i=1; $i<@listfirsts; $i++)
284
+ {
285
+ my $begin1x = $self->{TOKENS}{$listfirsts[$i-1]}->{XSTARTPOS} - $minx;
286
+ my $begin1y = $self->{TOKENS}{$listfirsts[$i-1]}->{YPOS};
287
+ my $begin2x = $self->{TOKENS}{$listfirsts[$i]}->{XSTARTPOS} - $minx;
288
+ my $begin2y = $self->{TOKENS}{$listfirsts[$i]}->{YPOS};
289
+
290
+ $output2 .= sprintf("jg.drawLine(scale*%.0f, %.0f, scale*%.0f, %.0f);\n", $begin1x, $begin1y, $begin2x, $begin2y);
291
+ }
292
+ }
293
+
294
+ if(scalar(@listlasts) > 1)
295
+ {
296
+ for(my $i=1; $i<@listlasts; $i++)
297
+ {
298
+ my $end1x = $self->{TOKENS}{$listlasts[$i-1]}->{XENDPOS} - $minx;
299
+ my $end1y = $self->{TOKENS}{$listlasts[$i-1]}->{YPOS};
300
+ my $end2x = $self->{TOKENS}{$listlasts[$i]}->{XENDPOS} - $minx;
301
+ my $end2y = $self->{TOKENS}{$listlasts[$i]}->{YPOS};
302
+
303
+ $output2 .= sprintf("jg.drawLine(scale*%.0f, %.0f, scale*%.0f, %.0f);\n", $end1x, $end1y, $end2x, $end2y);
304
+ }
305
+ }
306
+
307
+ my $output = "";
308
+
309
+ if($output2 ne "")
310
+ {
311
+ $output .= sprintf("jg.setColor(\"grey\");\n");
312
+ $output .= sprintf("jg.setStroke(Stroke.DOTTED);\n");
313
+ $output .= $output2;
314
+ }
315
+
316
+ foreach my $tknid(sort keys %{ $self->{TOKENS} })
317
+ {
318
+ $output .= $self->{TOKENS}{$tknid}->GetDraw($minx);
319
+ }
320
+
321
+ return $output;
322
+ }
323
+
324
+ 1;
325
+
SCTK/src/align2html/SegmentGroup.pm ADDED
@@ -0,0 +1,407 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ALIGN2HTML
2
+ # Author: Jerome Ajot
3
+ #
4
+ # This software was developed at the National Institute of Standards and Technology by
5
+ # employees of the Federal Government in the course of their official duties. Pursuant
6
+ # to title 17 Section 105 of the United States Code this software is not subject to
7
+ # copyright protection and is in the public domain. ALIGN2HTML is an experimental system.
8
+ # NIST assumes no responsibility whatsoever for its use by other parties, and makes no
9
+ # guarantees, expressed or implied, about its quality, reliability, or any other
10
+ # characteristic. We would appreciate acknowledgement if the software is used.
11
+ #
12
+ # THIS SOFTWARE IS PROVIDED "AS IS." With regard to this software, NIST MAKES NO EXPRESS
13
+ # OR IMPLIED WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING MERCHANTABILITY,
14
+ # OR FITNESS FOR A PARTICULAR PURPOSE.
15
+
16
+ package SegmentGroup;
17
+ use strict;
18
+ use Data::Dumper;
19
+
20
+ sub new
21
+ {
22
+ my $class = shift;
23
+ my $self = {};
24
+
25
+ $self->{ID} = shift;
26
+ $self->{REF} = {};
27
+ $self->{SYS} = {};
28
+ $self->{STARTYPOS} = 25;
29
+ $self->{YPOSSTEP} = 20;
30
+ $self->{MINX} = 10000000;
31
+ $self->{MAXX} = 0;
32
+ $self->{HEIGHT} = 0;
33
+ $self->{SPKRHEIGHT} = {};
34
+ $self->{HASFAKETIME} = 0;
35
+ $self->{SPKRYS} = {};
36
+ $self->{FILE} = shift;
37
+ $self->{CHANNEL} = shift;
38
+ $self->{NCORR} = 0;
39
+ $self->{NINS} = 0;
40
+ $self->{NSUB} = 0;
41
+ $self->{NDEL} = 0;
42
+ $self->{NREF} = 0;
43
+ $self->{NSPKRERR} = 0;
44
+ $self->{ET} = 0;
45
+ $self->{BT} = 0;
46
+ $self->{ALIGNED} = 0;
47
+
48
+ bless $self;
49
+ return $self;
50
+ }
51
+
52
+ sub unique
53
+ {
54
+ my %saw;
55
+ return grep(!$saw{$_}++, sort @_);
56
+ }
57
+
58
+ sub addRefSegment
59
+ {
60
+ my ($self, $seg) = @_;
61
+ $self->{REF}{$seg->{ID}} = $seg;
62
+ }
63
+
64
+ sub addSysSegment
65
+ {
66
+ my ($self, $seg) = @_;
67
+ $self->{SYS}{$seg->{ID}} = $seg;
68
+ }
69
+
70
+ sub ContainsFakeTimes
71
+ {
72
+ my ($self) = @_;
73
+
74
+ foreach my $segrefid(sort keys %{ $self->{REF} })
75
+ {
76
+ $self->{HASFAKETIME} = 1 if($self->{REF}{$segrefid}->{HASFAKETIME} == 1);
77
+ return;
78
+ }
79
+
80
+ foreach my $segsysid(sort keys %{ $self->{SYS} })
81
+ {
82
+ $self->{HASFAKETIME} = 1 if($self->{SYS}{$segsysid}->{HASFAKETIME} == 1);
83
+ return;
84
+ }
85
+ }
86
+
87
+ sub GetNumHypWords
88
+ {
89
+ my ($self) = @_;
90
+
91
+ my $number = 0;
92
+ foreach my $segsysid(keys %{ $self->{SYS} }) { $number += scalar keys %{ $self->{SYS}{$segsysid}->{TOKENS} } if(!($self->{SYS}{$segsysid}->HasOnlyOneFakeToken())); }
93
+ return $number;
94
+ }
95
+
96
+ sub GetToken
97
+ {
98
+ my ($self, $tokenID) = @_;
99
+
100
+ foreach my $segrefid(keys %{ $self->{REF} })
101
+ {
102
+ return $self->{REF}{$segrefid}->{TOKENS}{$tokenID} if(exists($self->{REF}{$segrefid}->{TOKENS}{$tokenID}));
103
+ }
104
+
105
+ foreach my $segsysid(keys %{ $self->{SYS} })
106
+ {
107
+ return $self->{SYS}{$segsysid}->{TOKENS}{$tokenID} if(exists($self->{SYS}{$segsysid}->{TOKENS}{$tokenID}));
108
+ }
109
+
110
+ return undef;
111
+ }
112
+
113
+ sub CalculateBeginEndTime
114
+ {
115
+ my ($self) = @_;
116
+
117
+ $self->{ET} = 0;
118
+ $self->{BT} = 1000000;
119
+
120
+ foreach my $segrefid(sort keys %{ $self->{REF} })
121
+ {
122
+ foreach my $tknid(sort keys %{ $self->{REF}{$segrefid}->{TOKENS} })
123
+ {
124
+ next if( ($self->{REF}{$segrefid}->{TOKENS}{$tknid}->{SEGBT} == 0) && ($self->{REF}{$segrefid}->{TOKENS}{$tknid}->{SEGET} == 0) && ($self->{REF}{$segrefid}->{TOKENS}{$tknid}->{TEXT} eq "") );
125
+ $self->{BT} = $self->{REF}{$segrefid}->{TOKENS}{$tknid}->{SEGBT} if($self->{REF}{$segrefid}->{TOKENS}{$tknid}->{SEGBT} < $self->{BT});
126
+ $self->{ET} = $self->{REF}{$segrefid}->{TOKENS}{$tknid}->{SEGET} if($self->{REF}{$segrefid}->{TOKENS}{$tknid}->{SEGET} > $self->{ET});
127
+ }
128
+ }
129
+
130
+ foreach my $segsysid(sort keys %{ $self->{SYS} })
131
+ {
132
+ foreach my $tknid(sort keys %{ $self->{SYS}{$segsysid}->{TOKENS} })
133
+ {
134
+ next if( ($self->{SYS}{$segsysid}->{TOKENS}{$tknid}->{BT} == 0) && ($self->{SYS}{$segsysid}->{TOKENS}{$tknid}->{BT} + $self->{SYS}{$segsysid}->{TOKENS}{$tknid}->{DUR} == 0) && ($self->{SYS}{$segsysid}->{TOKENS}{$tknid}->{TEXT} eq "") );
135
+ $self->{BT} = $self->{SYS}{$segsysid}->{TOKENS}{$tknid}->{BT} if($self->{SYS}{$segsysid}->{TOKENS}{$tknid}->{BT} < $self->{BT});
136
+ $self->{ET} = sprintf("%.3f", $self->{SYS}{$segsysid}->{TOKENS}{$tknid}->{BT} + $self->{SYS}{$segsysid}->{TOKENS}{$tknid}->{DUR}) if(sprintf("%.3f", $self->{SYS}{$segsysid}->{TOKENS}{$tknid}->{BT} + $self->{SYS}{$segsysid}->{TOKENS}{$tknid}->{DUR}) > $self->{ET});
137
+ }
138
+ }
139
+ }
140
+
141
+ sub CalculateMinMaxX
142
+ {
143
+ my ($self) = @_;
144
+
145
+ foreach my $segrefid(sort keys %{ $self->{REF} })
146
+ {
147
+ $self->{MINX} = $self->{REF}{$segrefid}->{MINX} if($self->{MINX} > $self->{REF}{$segrefid}->{MINX});
148
+ $self->{MAXX} = $self->{REF}{$segrefid}->{MAXX} if($self->{MAXX} < $self->{REF}{$segrefid}->{MAXX});
149
+ }
150
+
151
+ foreach my $segsysid(sort keys %{ $self->{SYS} })
152
+ {
153
+ $self->{MINX} = $self->{SYS}{$segsysid}->{MINX} if($self->{MINX} > $self->{SYS}{$segsysid}->{MINX});
154
+ $self->{MAXX} = $self->{SYS}{$segsysid}->{MAXX} if($self->{MAXX} < $self->{SYS}{$segsysid}->{MAXX});
155
+ }
156
+ }
157
+
158
+ sub CalculateHeigh
159
+ {
160
+ my ($self) = @_;
161
+
162
+ my %spkrYpos;
163
+
164
+ $self->{HEIGHT} = 2 * $self->{STARTYPOS} + $self->{YPOSSTEP};
165
+
166
+ foreach my $segrefid(sort keys %{ $self->{REF} })
167
+ {
168
+ my $spkrID = $self->{REF}{$segrefid}->{SPKRID};
169
+
170
+ if(!exists($spkrYpos{REF}{$spkrID}))
171
+ {
172
+ $spkrYpos{REF}{$spkrID} = 1;
173
+ $self->{SPKRHEIGHT}{$spkrID} = $self->{REF}{$segrefid}->{HEIGHT};
174
+ }
175
+ else
176
+ {
177
+ $self->{SPKRHEIGHT}{$spkrID} = $self->{REF}{$segrefid}->{HEIGHT} if($self->{REF}{$segrefid}->{HEIGHT} > $self->{SPKRHEIGHT}{$spkrID});
178
+ }
179
+ }
180
+
181
+ foreach my $segsysid(sort keys %{ $self->{SYS} })
182
+ {
183
+ my $spkrID = $self->{SYS}{$segsysid}->{SPKRID};
184
+
185
+ if(!exists($spkrYpos{SYS}{$spkrID}))
186
+ {
187
+ $spkrYpos{SYS}{$spkrID} = 1;
188
+ $self->{SPKRHEIGHT}{$spkrID} = $self->{SYS}{$segsysid}->{HEIGHT};
189
+ }
190
+ else
191
+ {
192
+ $self->{SPKRHEIGHT}{$spkrID} = $self->{SYS}{$segsysid}->{HEIGHT} if($self->{SYS}{$segsysid}->{HEIGHT} > $self->{SPKRHEIGHT}{$spkrID});
193
+ }
194
+ }
195
+
196
+ foreach my $idd (keys %{ $self->{SPKRHEIGHT} } )
197
+ {
198
+ $self->{HEIGHT} += $self->{SPKRHEIGHT}{$idd} + $self->{YPOSSTEP};
199
+ }
200
+
201
+ return $self->{HEIGHT};
202
+ }
203
+
204
+ sub SetYs
205
+ {
206
+ my ($self) = @_;
207
+
208
+ my $output = "";
209
+ my $currYpos = $self->{STARTYPOS};
210
+ my $YposStep = $self->{YPOSSTEP};
211
+
212
+ my %spkrYpos;
213
+
214
+ foreach my $segrefid(sort keys %{ $self->{REF} })
215
+ {
216
+ my $spkrID = $self->{REF}{$segrefid}->{SPKRID};
217
+ my $Ypos;
218
+
219
+ if(!exists($spkrYpos{REF}{$spkrID}))
220
+ {
221
+ $Ypos = $currYpos;
222
+ $spkrYpos{REF}{$spkrID} = $Ypos;
223
+ $currYpos += $self->{SPKRHEIGHT}{$spkrID} + $YposStep;
224
+ }
225
+ else
226
+ {
227
+ $Ypos = $spkrYpos{REF}{$spkrID};
228
+ }
229
+
230
+ $self->{REF}{$segrefid}->SetY($Ypos);
231
+ $self->{SPKRYS}{$spkrID} = $Ypos;
232
+ }
233
+
234
+ $currYpos += 2*$self->{YPOSSTEP};
235
+
236
+ foreach my $segsysid(sort keys %{ $self->{SYS} })
237
+ {
238
+ my $spkrID = $self->{SYS}{$segsysid}->{SPKRID};
239
+ my $Ypos;
240
+
241
+ if(!exists($spkrYpos{SYS}{$spkrID}))
242
+ {
243
+ $Ypos = $currYpos;
244
+ $spkrYpos{SYS}{$spkrID} = $Ypos;
245
+ $currYpos += $self->{SPKRHEIGHT}{$spkrID} + $YposStep;
246
+ }
247
+ else
248
+ {
249
+ $Ypos = $spkrYpos{SYS}{$spkrID};
250
+ }
251
+
252
+ $self->{SYS}{$segsysid}->SetY($Ypos);
253
+ $self->{SPKRYS}{$spkrID} = $Ypos;
254
+ }
255
+ }
256
+
257
+ sub GetFillREFHYP
258
+ {
259
+ my ($self, $maxscalewidth) = @_;
260
+ my $output = "";
261
+ my @valuessep1;
262
+
263
+ foreach my $spkrID(sort keys %{ $self->{SPKRYS} })
264
+ {
265
+ push(@valuessep1, $self->{SPKRYS}{$spkrID} - 25);
266
+ push(@valuessep1, $self->{SPKRYS}{$spkrID} + $self->{SPKRHEIGHT}{$spkrID});
267
+ }
268
+
269
+ my @valuessep = sort {$a <=> $b} @valuessep1;
270
+
271
+ my @refspkrs;
272
+ foreach my $segref (keys %{ $self->{REF} }) { push(@refspkrs, $self->{REF}{$segref}->{SPKRID}); }
273
+ my $nrefspkr = scalar unique @refspkrs;
274
+
275
+ my @sysspkrs;
276
+ foreach my $segsys (keys %{ $self->{SYS} }) { push(@sysspkrs, $self->{SYS}{$segsys}->{SPKRID}); }
277
+ my $nsysspkr = scalar unique @sysspkrs;
278
+
279
+ if($nrefspkr == 0)
280
+ {
281
+ my $y1 = $valuessep[0];
282
+ my $y2 = $valuessep[scalar(@valuessep) - 1];
283
+ $output .= sprintf("jg.setColor(\"#ffeeee\");\n");
284
+ $output .= sprintf("jg.fillRect(0, %.0f, scale*%.0f - 1, %.0f);\n", $y1 + 1, $maxscalewidth, $y2 - $y1 - 1);
285
+ }
286
+ elsif($nsysspkr == 0)
287
+ {
288
+ my $y1 = $valuessep[0];
289
+ my $y2 = $valuessep[scalar(@valuessep) - 1];
290
+ $output .= sprintf("jg.setColor(\"#eeffee\");\n");
291
+ $output .= sprintf("jg.fillRect(0, %.0f, scale*%.0f - 1, %.0f);\n", $y1 + 1, $maxscalewidth, $y2 - $y1 - 1);
292
+ }
293
+ else
294
+ {
295
+ my $y1 = $valuessep[0];
296
+ my $ym = ($valuessep[2*$nrefspkr - 1] + $valuessep[2*$nrefspkr])/2;
297
+ my $y2 = $valuessep[scalar(@valuessep) - 1];
298
+ $output .= sprintf("jg.setColor(\"#eeffee\");\n");
299
+ $output .= sprintf("jg.fillRect(0, %.0f, scale*%.0f - 1, %.0f);\n", $y1 + 1, $maxscalewidth, $ym - $y1 - 1);
300
+ $output .= sprintf("jg.setColor(\"#ffeeee\");\n");
301
+ $output .= sprintf("jg.fillRect(0, %.0f, scale*%.0f - 1, %.0f);\n", $ym - $y1 + 1, $maxscalewidth, $y2 - $ym -1);
302
+ }
303
+
304
+ return $output;
305
+ }
306
+
307
+ sub GetSeparationLines
308
+ {
309
+ my ($self, $maxscalewidth) = @_;
310
+ my $output = "";
311
+
312
+ $output .= sprintf("jg.setColor(\"black\");\n");
313
+ $output .= sprintf("jg.setFont(\"verdana\",\"12px\",Font.PLAIN);\n");
314
+
315
+ foreach my $spkrID(sort keys %{ $self->{SPKRYS} })
316
+ {
317
+ my $spkName = $spkrID;
318
+ $spkName =~ s/^ref://;
319
+ $spkName =~ s/^hyp://;
320
+ $output .= sprintf("jg.drawStringRect(\"%s\",%.0f, %.0f, scale*%.0f, \"left\");\n", $spkName, 0, $self->{SPKRYS}{$spkrID} - 8 + ($self->{SPKRHEIGHT}{$spkrID}-30)/2, $maxscalewidth);
321
+ }
322
+
323
+ $output .= sprintf("jg.setColor(\"yellow\");\n");
324
+ $output .= sprintf("jg.setStroke(1);\n");
325
+
326
+ my @valuessep1;
327
+
328
+ foreach my $spkrID(sort keys %{ $self->{SPKRYS} })
329
+ {
330
+ push(@valuessep1, $self->{SPKRYS}{$spkrID} - 25);
331
+ push(@valuessep1, $self->{SPKRYS}{$spkrID} + $self->{SPKRHEIGHT}{$spkrID});
332
+ }
333
+
334
+ my @valuessep = sort {$a <=> $b} @valuessep1;
335
+
336
+ $output .= sprintf("jg.drawLine(0, %.0f, scale*%.0f - 1, %.0f);\n", $valuessep[0], $maxscalewidth, $valuessep[0]);
337
+
338
+ for(my $i=1; $i<scalar(@valuessep)-1; $i += 2)
339
+ {
340
+ my $ypostmp = ($valuessep[$i] + $valuessep[$i + 1])/2;
341
+
342
+ $output .= sprintf("jg.drawLine(0, %.0f, scale*%.0f - 1, %.0f);\n", $ypostmp, $maxscalewidth, $ypostmp);
343
+ }
344
+
345
+ $output .= sprintf("jg.drawLine(0, %.0f, scale*%.0f - 1, %.0f);\n", $valuessep[scalar(@valuessep) - 1], $maxscalewidth, $valuessep[scalar(@valuessep) - 1]);
346
+
347
+ return $output;
348
+ }
349
+
350
+ sub Compute
351
+ {
352
+ my ($self) = @_;
353
+
354
+ foreach my $segrefid(sort keys %{ $self->{REF} })
355
+ {
356
+ $self->{REF}{$segrefid}->Compute();
357
+ }
358
+
359
+ foreach my $segsysid(sort keys %{ $self->{SYS} })
360
+ {
361
+ $self->{SYS}{$segsysid}->Compute();
362
+ }
363
+
364
+ $self->CalculateMinMaxX();
365
+ $self->CalculateHeigh();
366
+ $self->ContainsFakeTimes();
367
+ $self->SetYs();
368
+ $self->CalculateBeginEndTime();
369
+ }
370
+
371
+ sub isInSpeakers
372
+ {
373
+ my ($self, $spkr) = @_;
374
+
375
+ foreach my $segrefid(sort keys %{ $self->{REF} })
376
+ {
377
+ return 1 if($self->{REF}{$segrefid}->{SPKRID} =~ /^$spkr$/i);
378
+ }
379
+
380
+ foreach my $segsysid(sort keys %{ $self->{SYS} })
381
+ {
382
+ return 1 if($self->{SYS}{$segsysid}->{SPKRID} =~ /^$spkr$/i);
383
+ }
384
+
385
+ return 0;
386
+ }
387
+
388
+ sub GetDraw
389
+ {
390
+ my ($self, $decalx) = @_;
391
+ my $output = "";
392
+
393
+ foreach my $segrefid(sort keys %{ $self->{REF} })
394
+ {
395
+ $output .= $self->{REF}{$segrefid}->GetDraw($self->{MINX} - $decalx);
396
+ }
397
+
398
+ foreach my $segsysid(sort keys %{ $self->{SYS} })
399
+ {
400
+ $output .= $self->{SYS}{$segsysid}->GetDraw($self->{MINX} - $decalx);
401
+ }
402
+
403
+ return $output;
404
+ }
405
+
406
+ 1;
407
+
SCTK/src/align2html/Token.pm ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ALIGN2HTML
2
+ # Author: Jerome Ajot
3
+ #
4
+ # This software was developed at the National Institute of Standards and Technology by
5
+ # employees of the Federal Government in the course of their official duties. Pursuant
6
+ # to title 17 Section 105 of the United States Code this software is not subject to
7
+ # copyright protection and is in the public domain. ALIGN2HTML is an experimental system.
8
+ # NIST assumes no responsibility whatsoever for its use by other parties, and makes no
9
+ # guarantees, expressed or implied, about its quality, reliability, or any other
10
+ # characteristic. We would appreciate acknowledgement if the software is used.
11
+ #
12
+ # THIS SOFTWARE IS PROVIDED "AS IS." With regard to this software, NIST MAKES NO EXPRESS
13
+ # OR IMPLIED WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING MERCHANTABILITY,
14
+ # OR FITNESS FOR A PARTICULAR PURPOSE.
15
+
16
+ package Token;
17
+ use strict;
18
+ use Data::Dumper;
19
+
20
+ sub new
21
+ {
22
+ my $class = shift;
23
+ my $self = {};
24
+
25
+ $self->{ID} = shift;
26
+ $self->{BT} = shift;
27
+ $self->{DUR} = shift;
28
+ $self->{MID} = 0;
29
+ $self->{TEXT} = shift;
30
+ $self->{LENGTH} = 0;
31
+ $self->{XSTARTPOS} = 0;
32
+ $self->{XENDPOS} = 0;
33
+ $self->{YPOS} = 0;
34
+ $self->{XMIDPOS} = 0;
35
+ $self->{TEXTPOS} = "top";
36
+ $self->{WIDTHLINE} = 1;
37
+ $self->{PIXPERSEC} = 100;
38
+ $self->{REFORSYS} = shift;
39
+ $self->{PREVTKNID} = [()];
40
+ $self->{NEXTTKNID} = [()];
41
+ $self->{DISPLAY} = 0;
42
+ $self->{NUMPREV} = 0;
43
+ $self->{NUMNEXT} = 0;
44
+ $self->{SEGGRPID} = shift;
45
+ $self->{SEGID} = shift;
46
+ $self->{SPKRID} = shift;
47
+ $self->{CONF} = shift;
48
+ $self->{REALTIME} = 1;
49
+
50
+ my $tmpprev = shift;
51
+ my $tmpnext = shift;
52
+
53
+ $self->{SEGBT} = shift;
54
+ $self->{SEGET} = shift;
55
+
56
+ bless $self;
57
+
58
+ $self->{REALTIME} = 0 if( ($self->{BT} eq "") || ($self->{DUR} eq "") );
59
+
60
+ if($self->{REALTIME} == 0)
61
+ {
62
+ $self->{BT} = $self->{SEGBT};
63
+ $self->{DUR} = sprintf("%.3f", $self->{SEGET}-$self->{SEGBT});
64
+ }
65
+
66
+ $self->{MID} = sprintf("%.0f", $self->{BT} + $self->{DUR}/2);
67
+ $self->{XSTARTPOS} = sprintf("%.0f", $self->{PIXPERSEC}*$self->{BT});
68
+ $self->{XMIDPOS} = sprintf("%.0f", $self->{PIXPERSEC}*($self->{BT}+$self->{DUR}/2));
69
+ $self->{XENDPOS} = sprintf("%.0f", $self->{PIXPERSEC}*($self->{BT}+$self->{DUR}));
70
+ $self->{LENGTH} = sprintf("%.0f", $self->{PIXPERSEC}*$self->{DUR});
71
+ $self->{TEXTPOS} = "bottom" if($self->{REFORSYS} eq "SYS");
72
+
73
+ push(@{ $self->{PREVTKNID} }, sort {$a <=> $b} split(/\|/, $tmpprev) );
74
+ push(@{ $self->{NEXTTKNID} }, sort {$a <=> $b} split(/\|/, $tmpnext) );
75
+
76
+ $self->{NUMPREV} = scalar( @{ $self->{PREVTKNID} } );
77
+ $self->{NUMNEXT} = scalar( @{ $self->{NEXTTKNID} } );
78
+
79
+ return $self;
80
+ }
81
+
82
+ sub MakeFakeTime
83
+ {
84
+ my ($self, $beginindex, $endindex, $maxind) = @_;
85
+
86
+ $self->{DUR} = sprintf("%.3f", ($self->{SEGET} - $self->{SEGBT})*( ($endindex - $beginindex)/$maxind ) );
87
+ $self->{BT} = sprintf("%.3f", $self->{SEGBT} + ($self->{SEGET} - $self->{SEGBT})*$beginindex/$maxind);
88
+ $self->{MID} = sprintf("%.0f", $self->{BT} + $self->{DUR}/2);
89
+ $self->{XSTARTPOS} = sprintf("%.0f", $self->{PIXPERSEC}*$self->{BT});
90
+ $self->{XMIDPOS} = sprintf("%.0f", $self->{PIXPERSEC}*($self->{BT}+$self->{DUR}/2));
91
+ $self->{XENDPOS} = sprintf("%.0f", $self->{PIXPERSEC}*($self->{BT}+$self->{DUR}));
92
+ $self->{LENGTH} = sprintf("%.0f", $self->{PIXPERSEC}*$self->{DUR});
93
+ }
94
+
95
+ sub DoDisplay
96
+ {
97
+ my ($self) = @_;
98
+ $self->{DISPLAY} = 1;
99
+ }
100
+
101
+ sub AddPrevToken
102
+ {
103
+ my ($self, $prevtknid) = @_;
104
+ push(@{ $self->{PREVTKNID} }, $prevtknid);
105
+ }
106
+
107
+ sub AddNextToken
108
+ {
109
+ my ($self, $nexttknid) = @_;
110
+ push(@{ $self->{NEXTTKNID} }, $nexttknid);
111
+ }
112
+
113
+ sub SetYPos
114
+ {
115
+ my ($self, $ypos) = @_;
116
+ $self->{YPOS} += $ypos;
117
+ }
118
+
119
+
120
+ sub SetWidthLine
121
+ {
122
+ my ($self, $lwidth) = @_;
123
+ $self->{WIDTHLINE} = $lwidth;
124
+ }
125
+
126
+ sub IsFakeToken
127
+ {
128
+ my ($self) = @_;
129
+ return( ($self->{SEGBT} == 0) && ($self->{SEGET} == 0) && ($self->{TEXT} eq "") );
130
+ }
131
+
132
+ sub GetDraw
133
+ {
134
+ my ($self, $minx) = @_;
135
+ my $output = "";
136
+
137
+ return $output if(! $self->{DISPLAY});
138
+
139
+ if($self->{TEXT} ne "")
140
+ {
141
+ my $modiftexty = ($self->{TEXTPOS} eq "top" ? -17 : 6);
142
+ my $bullet = "images/white_dk.gif";
143
+ $bullet = "images/white_lt.gif" if($self->{REALTIME} == 0);
144
+
145
+ $output .= sprintf("jg.setColor(\"DimGray\");\n");
146
+ $output .= sprintf("jg.setStroke(%.0f);\n", $self->{WIDTHLINE});
147
+ $output .= sprintf("jg.drawLine(%.0f*scale, %.0f, %.0f*scale, %.0f);\n", $self->{XSTARTPOS} - $minx, $self->{YPOS}, $self->{XENDPOS} - $minx, $self->{YPOS});
148
+ $output .= sprintf("jg.setFont(\"arial\",\"11px\",Font.PLAIN);\n");
149
+ $output .= sprintf("jg.drawStringRect(\"%s\", %.0f*scale + 1, %.0f, %.0f*scale - 1, \"center\");\n", $self->{TEXT}, $self->{XSTARTPOS} - $minx, $self->{YPOS}+$modiftexty, $self->{LENGTH});
150
+ $output .= sprintf("jg.drawImage(\"%s\", %.0f*scale - 7, %.0f - 7, 14, 14);\n", $bullet, $self->{XSTARTPOS} - $minx, $self->{YPOS});
151
+ $output .= sprintf("jg.drawImage(\"%s\", %.0f*scale - 7, %.0f - 7, 14, 14);\n", $bullet, $self->{XENDPOS} - $minx, $self->{YPOS});
152
+ }
153
+ elsif(!( ($self->{SEGBT} == 0) && ($self->{SEGET} == 0) && ($self->{TEXT} eq "") ) )
154
+ {
155
+ $output .= sprintf("jg.setColor(\"brown\");\n");
156
+ $output .= sprintf("jg.setStroke(%.0f);\n", $self->{WIDTHLINE});
157
+ $output .= sprintf("jg.drawLine(%.0f*scale, %.0f, %.0f*scale, %.0f);\n", $self->{XSTARTPOS} - $minx, $self->{YPOS}, $self->{XENDPOS} - $minx, $self->{YPOS});
158
+ $output .= sprintf("jg.drawLine(%.0f*scale, %.0f, %.0f*scale, %.0f);\n", $self->{XSTARTPOS} - $minx, $self->{YPOS} - 4, $self->{XSTARTPOS} - $minx, $self->{YPOS} + 4);
159
+ $output .= sprintf("jg.drawLine(%.0f*scale, %.0f, %.0f*scale, %.0f);\n", $self->{XENDPOS} - $minx, $self->{YPOS} - 4, $self->{XENDPOS} - $minx, $self->{YPOS} + 4);
160
+ }
161
+
162
+ return $output;
163
+ }
164
+
165
+ 1;
166
+
SCTK/src/align2html/align2html-main.pl ADDED
@@ -0,0 +1,1436 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/perl -w
2
+
3
+ # ALIGN2HTML
4
+ # Author: Jerome Ajot
5
+ #
6
+ # This software was developed at the National Institute of Standards and Technology by
7
+ # employees of the Federal Government in the course of their official duties. Pursuant
8
+ # to title 17 Section 105 of the United States Code this software is not subject to
9
+ # copyright protection and is in the public domain. ALIGN2HTML is an experimental system.
10
+ # NIST assumes no responsibility whatsoever for its use by other parties, and makes no
11
+ # guarantees, expressed or implied, about its quality, reliability, or any other
12
+ # characteristic. We would appreciate acknowledgement if the software is used.
13
+ #
14
+ # THIS SOFTWARE IS PROVIDED "AS IS." With regard to this software, NIST MAKES NO EXPRESS
15
+ # OR IMPLIED WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING MERCHANTABILITY,
16
+ # OR FITNESS FOR A PARTICULAR PURPOSE.
17
+
18
+ use strict;
19
+ use Getopt::Long;
20
+ use Data::Dumper;
21
+ use File::Path;
22
+
23
+ ### Begin Local Modules
24
+ use SegmentGroup;
25
+ use Segment;
26
+ use Token;
27
+ ### End Local Modules
28
+
29
+ Getopt::Long::Configure(qw( auto_abbrev no_ignore_case ));
30
+
31
+ my $VERSION = "0.6";
32
+ my $AlignFile = "";
33
+ my $MapFile = "";
34
+ my $Outputdir = "";
35
+ my $NonLinearSegments = 0;
36
+ my $pixelpersec = 100;
37
+ my $maxscalewidth = 0;
38
+
39
+ ## This variable says if the program is installed as a standalone executable
40
+ my $Installed = 0;
41
+
42
+ sub usage
43
+ {
44
+ print "perl align2html.pl [OPTIONS] -i alignfile -o outputdir\n";
45
+ print "Version: $VERSION\n";
46
+ print "\n";
47
+ print "Required file arguments:\n";
48
+ print " -a, --alignfile Path to the Alignment file.\n";
49
+ print " -o, --outputdir Path to the output directory.\n";
50
+ print "\n";
51
+ print "Options\n";
52
+ print " -m, --mapfile Path to the Mapping file.\n";
53
+ print "\n";
54
+ }
55
+
56
+ sub extractJavaImages
57
+ {
58
+ my ($outDir) = @_;
59
+ die "HERE DOCUMENT NOT BUILT";
60
+ }
61
+
62
+ sub unique
63
+ {
64
+ my %saw;
65
+ return grep(!$saw{$_}++, sort @_);
66
+ }
67
+
68
+ my %SegGroups;
69
+ my %Alignments;
70
+ my %FileChannelSG;
71
+ my %Overlap;
72
+ my %CumulOverlap;
73
+
74
+ sub addSGLine
75
+ {
76
+ my ($inputline) = @_;
77
+
78
+ my $SG;
79
+ my $Segmnt;
80
+ my $SYSREF = "";
81
+ my $SegID;
82
+ my $Tokn;
83
+ my $SpkrID;
84
+
85
+ my $SG_SegGrpID = $inputline->[1];
86
+ my $SG_SegGrpFile = $inputline->[2];
87
+ my $SG_SegGrpChan = $inputline->[3];
88
+ my $SG_RefSegID = $inputline->[5];
89
+ my $SG_HypSegID = $inputline->[16];
90
+
91
+ my $ok = 0;
92
+
93
+ if($SG_RefSegID ne "" && $inputline->[9] ne "")
94
+ {
95
+ $SYSREF = "REF";
96
+ $SegID = $SG_RefSegID;
97
+ $SpkrID = "ref:" . $inputline->[8];
98
+
99
+ my $dur = 0;
100
+ $dur = sprintf("%.3f", $inputline->[11]-$inputline->[10]) if( ($inputline->[10] ne "") || ($inputline->[11] ne "") );
101
+
102
+ $Tokn = new Token($inputline->[9], $inputline->[10], $dur, $inputline->[12], $SYSREF, $inputline->[1], $inputline->[5], $SpkrID, $inputline->[13], $inputline->[14], $inputline->[15], $inputline->[6], $inputline->[7]);
103
+ $ok = 1;
104
+ }
105
+
106
+ if($SG_HypSegID ne "" && $inputline->[20] ne "")
107
+ {
108
+ $SYSREF = "SYS";
109
+ $SegID = $SG_HypSegID;
110
+ $SpkrID = "hyp:" . $inputline->[19];
111
+
112
+ my $dur = 0;
113
+ $dur = sprintf("%.3f", $inputline->[22]-$inputline->[21]) if( ($inputline->[21] ne "") || ($inputline->[22] ne "") );
114
+
115
+ $Tokn = new Token($inputline->[20], $inputline->[21], $dur, $inputline->[23], $SYSREF, $inputline->[1], $inputline->[16], $SpkrID, $inputline->[24], $inputline->[25], $inputline->[26], $inputline->[17], $inputline->[18]);
116
+ $ok = 1;
117
+ }
118
+
119
+ if($ok)
120
+ {
121
+ $SegGroups{$SG_SegGrpID} = new SegmentGroup($SG_SegGrpID, $SG_SegGrpFile, $SG_SegGrpChan) if(!exists($SegGroups{$SG_SegGrpID}));
122
+ $SG = $SegGroups{$SG_SegGrpID};
123
+
124
+ if(!exists( $SG->{$SYSREF}{$SegID} ))
125
+ {
126
+ $Segmnt = new Segment($SegID, $SpkrID);
127
+
128
+ $SG->addSysSegment($Segmnt) if($SYSREF eq "SYS");
129
+ $SG->addRefSegment($Segmnt) if($SYSREF eq "REF");
130
+ }
131
+ else
132
+ {
133
+ $Segmnt = $SG->{$SYSREF}{$SegID};
134
+ }
135
+
136
+ $Tokn->DoDisplay();
137
+ $Segmnt->AddToken($Tokn);
138
+ }
139
+ }
140
+
141
+ sub addAlignments
142
+ {
143
+ my ($inputline) = @_;
144
+
145
+ my $SG_SegGrpID = $inputline->[1];
146
+ my $SG_Eval = $inputline->[4];
147
+ my $SG_RefTknID = $inputline->[9];
148
+ my $SG_HypTknID = $inputline->[20];
149
+
150
+ push( @{ $Alignments{$SG_SegGrpID} }, [($SG_Eval, $SG_RefTknID, $SG_HypTknID)]);
151
+ $SegGroups{$SG_SegGrpID}->{ALIGNED} = 1;
152
+
153
+ if($SG_RefTknID ne "")
154
+ {
155
+ $SegGroups{$SG_SegGrpID}->GetToken($SG_RefTknID)->SetWidthLine(2);
156
+ $SegGroups{$SG_SegGrpID}->GetToken($SG_RefTknID)->DoDisplay();
157
+ }
158
+
159
+ if($SG_HypTknID ne "")
160
+ {
161
+ $SegGroups{$SG_SegGrpID}->GetToken($SG_HypTknID)->SetWidthLine(2);
162
+ $SegGroups{$SG_SegGrpID}->GetToken($SG_HypTknID)->DoDisplay();
163
+ }
164
+ }
165
+
166
+ sub loadAlignFile
167
+ {
168
+ my ($alignfile) = @_;
169
+ my $linenum = 0;
170
+
171
+ open(ALIGNFILE, $alignfile) or die "Unable to open for read alignfile file '$alignfile'";
172
+
173
+ while (<ALIGNFILE>)
174
+ {
175
+ chomp;
176
+ my $fileline = $_;
177
+ $linenum++;
178
+
179
+ next if($fileline !~ /^\[ALIGNMENT\]/);
180
+ next if($fileline =~ /^\[ALIGNMENT\]\s*Aligned/);
181
+
182
+ $fileline =~ s/^\[ALIGNMENT\]//g;
183
+ $fileline =~ s/\s+//g;
184
+ $fileline =~ s/,/, /g;
185
+
186
+ my @spliteedline = split(",", $fileline);
187
+
188
+ foreach (@spliteedline) { $_ =~ s/\s+//g; }
189
+
190
+ addSGLine(\@spliteedline) if($spliteedline[0] eq "SG" );
191
+ addAlignments(\@spliteedline) if($spliteedline[0] eq "YES");
192
+ }
193
+
194
+ close(ALIGNFILE);
195
+ }
196
+
197
+ sub GetHTMLHeader
198
+ {
199
+ my ($ID) = @_;
200
+
201
+ my $out = "";
202
+
203
+ $out .= "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n";
204
+ $out .= "\n";
205
+ $out .= "<html>\n";
206
+ $out .= "<head>\n";
207
+ $out .= "<meta content=\"text/html; charset=utf-8\" http-equiv=\"content-type\">\n";
208
+ $out .= "<title>Segment Group ID $ID</title>\n";
209
+ $out .= "<script type=\"text/javascript\" src=\"js/wz_jsgraphics.js\"></script>\n";
210
+ $out .= "<script type=\"text/javascript\">\n";
211
+ $out .= "<!--\n";
212
+ $out .= "var jg;\n";
213
+ $out .= "var scale = 1;\n";
214
+ $out .= "\n";
215
+ $out .= "function Init()\n";
216
+ $out .= "{\n";
217
+ $out .= "jg = new jsGraphics(\"Graph\");\n";
218
+ $out .= "scale = 1;\n";
219
+ $out .= "}\n";
220
+ $out .= "\n";
221
+ $out .= "function myDraw()\n";
222
+ $out .= "{\n";
223
+ $out .= "jg.clear();\n";
224
+
225
+ return $out;
226
+ }
227
+
228
+ sub GetHTMLFooter
229
+ {
230
+ my ($end, $heigh, $warning, $SG) = @_;
231
+
232
+ my $out = "";
233
+
234
+ $out .= "jg.paint();\n";
235
+ $out .= "}\n";
236
+ $out .= "\n";
237
+ $out .= "//-->\n";
238
+ $out .= "</script>\n";
239
+ $out .= "</head>\n";
240
+ $out .= "\n";
241
+ $out .= "<body bgcolor=\"white\" onload=\"Init(); myDraw()\">\n";
242
+ $out .= "\n";
243
+ $out .= sprintf("<div id=\"Graph\" style=\"background-color:white;height:%dpx;width:%dpx;border-style:solid;border-width:0;position:relative;top:0;left:0;\"></div>\n", $heigh, $end);
244
+ $out .= "\n";
245
+ $out .= "<font face=\"courier\">\n";
246
+ $out .= "<a href=\"#\" onclick=\"scale -= 0.5; myDraw(); return false\">[-5]</a>\n";
247
+ $out .= "<a href=\"#\" onclick=\"scale -= 0.1; myDraw(); return false\">[-]</a>\n";
248
+ $out .= "<a href=\"#\" onclick=\"scale = 1; myDraw(); return false\">[Reset]</a>\n";
249
+ $out .= "<a href=\"#\" onclick=\"scale += 0.1; myDraw(); return false\">[+]</a>\n";
250
+ $out .= "<a href=\"#\" onclick=\"scale += 0.5; myDraw(); return false\">[+5]</a>\n";
251
+
252
+
253
+
254
+ $out .= "</font>\n";
255
+ $out .= PrintMapping($SG);
256
+ $out .= PrintWarning() if($warning == 1);
257
+ $out .= "</body>\n";
258
+ $out .= "</html>\n";
259
+
260
+ return $out;
261
+ }
262
+
263
+ sub CalculateMaxScale
264
+ {
265
+ my ($start, $end, $stepsec, $heigh) = @_;
266
+ my $beginxline = $pixelpersec*sprintf("%.0f", $start/$pixelpersec);
267
+ my $endxline = $pixelpersec*sprintf("%.0f", $end/$pixelpersec);
268
+
269
+ $beginxline -= $pixelpersec if( ($beginxline > $start) && ($beginxline > $pixelpersec) );
270
+ $endxline += $pixelpersec if($endxline < $end);
271
+ $maxscalewidth = $endxline - $start + $pixelpersec;
272
+ }
273
+
274
+ sub GetDrawScale
275
+ {
276
+ my ($start, $end, $stepsec, $heigh) = @_;
277
+
278
+ my $output = "";
279
+ $output .= sprintf("jg.setColor(\"orange\");\n");
280
+ $output .= sprintf("jg.setStroke(Stroke.DOTTED);\n");
281
+ $output .= sprintf("jg.setFont(\"arial\",\"8px\",Font.BOLD);\n");
282
+
283
+ my $beginxline = $pixelpersec*sprintf("%.0f", $start/$pixelpersec);
284
+ my $endxline = $pixelpersec*sprintf("%.0f", $end/$pixelpersec);
285
+
286
+ $beginxline -= $pixelpersec if( ($beginxline > $start) && ($beginxline > $pixelpersec) );
287
+ $endxline += $pixelpersec if($endxline < $end);
288
+
289
+ for(my $i=$beginxline; $i<=$endxline; $ i += $stepsec*$pixelpersec)
290
+ {
291
+ $output .= sprintf("jg.drawLine(scale*%.0f, 0, scale*%.0f, %.0f);\n", $i - $start + $pixelpersec, $i - $start + $pixelpersec, $heigh);
292
+ $output .= sprintf("jg.drawStringRect(\"%s\", scale*%.1f - 9, %.0f + 2, 20, \"center\");\n", $i/$pixelpersec, $i - $start + $pixelpersec, $heigh);
293
+ }
294
+
295
+ return $output;
296
+ }
297
+
298
+ sub LinkToken
299
+ {
300
+ my ($tkn1x, $tkn1y, $tkn2x, $tkn2y, $decalx, $type) = @_;
301
+
302
+ my $color = "black";
303
+ $color = "blue" if($type eq "spkrerr");
304
+ $color = "red" if($type eq "sub");
305
+ $color = "green"if($type eq "corr");
306
+
307
+ my $out = "";
308
+ $out .= sprintf("jg.setColor(\"%s\");\n", $color);
309
+ $out .= sprintf("jg.setStroke(2);\n");
310
+ $out .= sprintf("jg.drawLine(%.0f*scale, %.0f, %.0f*scale, %.0f);\n", $tkn1x - $decalx, $tkn1y, $tkn2x - $decalx, $tkn2y);
311
+
312
+ return $out;
313
+ }
314
+
315
+ sub InsSubToken
316
+ {
317
+ my ($tknx, $tkny, $decalx, $type) = @_;
318
+
319
+ my $multi = 1;
320
+ $multi = -1 if($type eq "SYS");
321
+
322
+ my $color = "black";
323
+
324
+ my $out = "";
325
+ $out .= sprintf("jg.setColor(\"%s\");\n", $color);
326
+ $out .= sprintf("jg.setStroke(1);\n");
327
+ $out .= sprintf("jg.drawLine(%.0f*scale, %.0f, %.0f*scale, %.0f);\n", $tknx - $decalx, $tkny, $tknx - $decalx, $tkny + $multi*13);
328
+ $out .= sprintf("jg.drawLine(%.0f*scale - 8, %.0f, %.0f*scale + 8, %.0f);\n", $tknx - $decalx, $tkny + $multi*13 , $tknx - $decalx, $tkny + $multi*13);
329
+ $out .= sprintf("jg.drawLine(%.0f*scale - 5, %.0f, %.0f*scale + 5, %.0f);\n", $tknx - $decalx, $tkny + $multi*15 , $tknx - $decalx, $tkny + $multi*15);
330
+ $out .= sprintf("jg.drawLine(%.0f*scale - 2, %.0f, %.0f*scale + 2, %.0f);\n", $tknx - $decalx, $tkny + $multi*17 , $tknx - $decalx, $tkny + $multi*17);
331
+
332
+ return $out;
333
+ }
334
+
335
+ sub InsOptSubToken
336
+ {
337
+ my ($tknx, $tkny, $decalx, $type) = @_;
338
+
339
+ my $multi = 1;
340
+ $multi = -1 if($type eq "SYS");
341
+
342
+ my $color = "green";
343
+
344
+ my $out = "";
345
+ $out .= sprintf("jg.setColor(\"%s\");\n", $color);
346
+ $out .= sprintf("jg.setStroke(1);\n");
347
+ $out .= sprintf("jg.drawLine(%.0f*scale, %.0f, %.0f*scale, %.0f);\n", $tknx - $decalx, $tkny, $tknx - $decalx, $tkny + $multi*13);
348
+ $out .= sprintf("jg.drawLine(%.0f*scale - 8, %.0f, %.0f*scale + 8, %.0f);\n", $tknx - $decalx, $tkny + $multi*13 , $tknx - $decalx, $tkny + $multi*13);
349
+ $out .= sprintf("jg.drawLine(%.0f*scale - 5, %.0f, %.0f*scale + 5, %.0f);\n", $tknx - $decalx, $tkny + $multi*15 , $tknx - $decalx, $tkny + $multi*15);
350
+ $out .= sprintf("jg.drawLine(%.0f*scale - 2, %.0f, %.0f*scale + 2, %.0f);\n", $tknx - $decalx, $tkny + $multi*17 , $tknx - $decalx, $tkny + $multi*17);
351
+
352
+ return $out;
353
+ }
354
+
355
+ sub DrawLinkToken
356
+ {
357
+ my ($sg, $tknrefid, $tknhypid, $decalx, $type) = @_;
358
+
359
+ my $tknref;
360
+ my $tknhyp;
361
+
362
+ if($type eq "I")
363
+ {
364
+ $sg->{NINS}++;
365
+ $tknhyp = $sg->GetToken($tknhypid);
366
+ return InsSubToken($tknhyp->{XMIDPOS}, $tknhyp->{YPOS}, $sg->{MINX} - $pixelpersec, $tknhyp->{REFORSYS});
367
+ }
368
+
369
+ if($type eq "D")
370
+ {
371
+ $sg->{NDEL}++;
372
+ $sg->{NREF}++;
373
+ $tknref = $sg->GetToken($tknrefid);
374
+ return InsSubToken($tknref->{XMIDPOS}, $tknref->{YPOS}, $sg->{MINX} - $pixelpersec, $tknref->{REFORSYS});
375
+ }
376
+
377
+ if($type eq "C")
378
+ {
379
+ $sg->{NCORR}++;
380
+ $tknref = $sg->GetToken($tknrefid);
381
+ $tknhyp = $sg->GetToken($tknhypid);
382
+
383
+ my $refdef = 0;
384
+ $refdef = 1 if($tknrefid ne "");
385
+
386
+ my $hypdef = 0;
387
+ $hypdef = 1 if($tknhypid ne "");
388
+
389
+ $sg->{NREF}++ if($refdef);
390
+
391
+ return LinkToken($tknref->{XMIDPOS}, $tknref->{YPOS}, $tknhyp->{XMIDPOS}, $tknhyp->{YPOS}, $sg->{MINX} - $pixelpersec, "corr") if($refdef && $hypdef);
392
+ return InsOptSubToken($tknref->{XMIDPOS}, $tknref->{YPOS}, $sg->{MINX} - $pixelpersec, $tknref->{REFORSYS}) if($refdef && !$hypdef);
393
+ return InsOptSubToken($tknhyp->{XMIDPOS}, $tknhyp->{YPOS}, $sg->{MINX} - $pixelpersec, $tknhyp->{REFORSYS}) if(!$refdef && $hypdef);
394
+ }
395
+
396
+ if($type eq "S")
397
+ {
398
+ $sg->{NSUB}++;
399
+ $sg->{NREF}++;
400
+ $tknref = $sg->GetToken($tknrefid);
401
+ $tknhyp = $sg->GetToken($tknhypid);
402
+ return LinkToken($tknref->{XMIDPOS}, $tknref->{YPOS}, $tknhyp->{XMIDPOS}, $tknhyp->{YPOS}, $sg->{MINX} - $pixelpersec, "sub");
403
+ }
404
+
405
+ if($type eq "P")
406
+ {
407
+ $sg->{NSPKRERR}++;
408
+ $sg->{NREF}++;
409
+ $tknref = $sg->GetToken($tknrefid);
410
+ $tknhyp = $sg->GetToken($tknhypid);
411
+ return LinkToken($tknref->{XMIDPOS}, $tknref->{YPOS}, $tknhyp->{XMIDPOS}, $tknhyp->{YPOS}, $sg->{MINX} - $pixelpersec, "spkrerr");
412
+ }
413
+
414
+ die "Unknown type $type";
415
+ }
416
+
417
+ sub PrintWarning
418
+ {
419
+ return "<p>WARNING: Some words do not have times specified for them. For these cases, word times <img src='images/white_lt.gif' border='0' /> are estimated from the segment times.</p>\n";
420
+ }
421
+
422
+ sub PrintMapping
423
+ {
424
+ my($SG) = @_;
425
+ my $out = "";
426
+ my @listmapping;
427
+
428
+ if($MapFile ne "")
429
+ {
430
+ $out .= "<br><br>MAPPING:<br>\n";
431
+
432
+ open(MAPFILE, $MapFile) or die "$?";
433
+
434
+ while (<MAPFILE>)
435
+ {
436
+ chomp;
437
+ next if($_ =~ /^File,Channel,RefSpeaker,SysSpeaker,isMapped,timeOverlap$/);
438
+
439
+ my @info = split(/,/, $_);
440
+
441
+ if($info[4] eq "mapped")
442
+ {
443
+ my $tmp1 = "ref:" . uc($info[2]);
444
+ my $tmp2 = "hyp:" . uc($info[3]);
445
+
446
+ if($SG->isInSpeakers($tmp1) == 1 && $SG->isInSpeakers($tmp2) == 1)
447
+ {
448
+ $tmp1 =~ s/^ref://;
449
+ $tmp1 =~ s/^hyp://;
450
+ $tmp2 =~ s/^ref://;
451
+ $tmp2 =~ s/^hyp://;
452
+ push(@listmapping, "$tmp1 <=> $tmp2<br>\n");
453
+ }
454
+ }
455
+ }
456
+
457
+ close MAPFILE;
458
+
459
+ my @listsorted = sort(@listmapping);
460
+
461
+ foreach my $mapp (@listsorted)
462
+ {
463
+ $out .= "$mapp\n";
464
+ }
465
+ }
466
+
467
+ return $out;
468
+ }
469
+
470
+ sub DrawKey
471
+ {
472
+ my ($ystart) = @_;
473
+
474
+ my $ystartpos = $ystart;
475
+
476
+ my $out = "";
477
+ $out .= sprintf("jg.setFont(\"verdana\",\"12px\",Font.PLAIN);\n");
478
+ $out .= sprintf("jg.setStroke(1);\n");
479
+
480
+ $out .= sprintf("jg.setColor(\"black\");\n");
481
+ $out .= sprintf("jg.drawLine(%.0f, %.0f, %.0f, %.0f);\n" , 15, $ystartpos , 15, $ystartpos + 13);
482
+ $out .= sprintf("jg.drawLine(%.0f - 8, %.0f, %.0f + 8, %.0f);\n", 15, $ystartpos + 13 , 15, $ystartpos + 13);
483
+ $out .= sprintf("jg.drawLine(%.0f - 5, %.0f, %.0f + 5, %.0f);\n", 15, $ystartpos + 15 , 15, $ystartpos + 15);
484
+ $out .= sprintf("jg.drawLine(%.0f - 2, %.0f, %.0f + 2, %.0f);\n", 15, $ystartpos + 17 , 15, $ystartpos + 17);
485
+ $out .= sprintf("jg.drawStringRect(\"%s\", %.0f, %.0f, 100, \"left\");\n", "Deletion", 50, $ystartpos + 4);
486
+
487
+ $out .= sprintf("jg.setColor(\"green\");\n");
488
+ $out .= sprintf("jg.drawLine(%.0f, %.0f, %.0f, %.0f);\n" , 215, $ystartpos , 215, $ystartpos + 13);
489
+ $out .= sprintf("jg.drawLine(%.0f - 8, %.0f, %.0f + 8, %.0f);\n", 215, $ystartpos + 13 , 215, $ystartpos + 13);
490
+ $out .= sprintf("jg.drawLine(%.0f - 5, %.0f, %.0f + 5, %.0f);\n", 215, $ystartpos + 15 , 215, $ystartpos + 15);
491
+ $out .= sprintf("jg.drawLine(%.0f - 2, %.0f, %.0f + 2, %.0f);\n", 215, $ystartpos + 17 , 215, $ystartpos + 17);
492
+ $out .= sprintf("jg.drawStringRect(\"%s\", %.0f, %.0f, 200, \"left\");\n", "Optionally Deletable", 250, $ystartpos + 4);
493
+
494
+ $ystartpos += 50;
495
+
496
+ $out .= sprintf("jg.setColor(\"black\");\n");
497
+ $out .= sprintf("jg.drawLine(%.0f, %.0f, %.0f, %.0f);\n" , 15, $ystartpos , 15, $ystartpos - 13);
498
+ $out .= sprintf("jg.drawLine(%.0f - 8, %.0f, %.0f + 8, %.0f);\n", 15, $ystartpos - 13 , 15, $ystartpos - 13);
499
+ $out .= sprintf("jg.drawLine(%.0f - 5, %.0f, %.0f + 5, %.0f);\n", 15, $ystartpos - 15 , 15, $ystartpos - 15);
500
+ $out .= sprintf("jg.drawLine(%.0f - 2, %.0f, %.0f + 2, %.0f);\n", 15, $ystartpos - 17 , 15, $ystartpos - 17);
501
+ $out .= sprintf("jg.drawStringRect(\"%s\", %.0f, %.0f, 100, \"left\");\n", "Insertion", 50, $ystartpos - 17);
502
+
503
+ $out .= sprintf("jg.setColor(\"green\");\n");
504
+ $out .= sprintf("jg.drawLine(%.0f, %.0f, %.0f, %.0f);\n" , 215, $ystartpos , 215, $ystartpos - 13);
505
+ $out .= sprintf("jg.drawLine(%.0f - 8, %.0f, %.0f + 8, %.0f);\n", 215, $ystartpos - 13 , 215, $ystartpos - 13);
506
+ $out .= sprintf("jg.drawLine(%.0f - 5, %.0f, %.0f + 5, %.0f);\n", 215, $ystartpos - 15 , 215, $ystartpos - 15);
507
+ $out .= sprintf("jg.drawLine(%.0f - 2, %.0f, %.0f + 2, %.0f);\n", 215, $ystartpos - 17 , 215, $ystartpos - 17);
508
+ $out .= sprintf("jg.drawStringRect(\"%s\", %.0f, %.0f, 200, \"left\");\n", "Optionally Insertable", 250, $ystartpos - 17);
509
+
510
+ $ystartpos += 15;
511
+
512
+ $out .= sprintf("jg.setStroke(2);\n");
513
+
514
+ $out .= sprintf("jg.setColor(\"green\");\n");
515
+ $out .= sprintf("jg.drawLine(%.0f, %.0f, %.0f, %.0f);\n" , 205, $ystartpos , 225, $ystartpos);
516
+ $out .= sprintf("jg.drawStringRect(\"%s\", %.0f, %.0f, 100, \"left\");\n", "Correct", 250, $ystartpos - 7);
517
+
518
+ $out .= sprintf("jg.setColor(\"red\");\n");
519
+ $out .= sprintf("jg.drawLine(%.0f, %.0f, %.0f, %.0f);\n" , 5, $ystartpos , 25, $ystartpos);
520
+ $out .= sprintf("jg.drawStringRect(\"%s\", %.0f, %.0f, 100, \"left\");\n", "Substitution", 50, $ystartpos - 7);
521
+
522
+ $ystartpos += 25;
523
+
524
+ $out .= sprintf("jg.setColor(\"blue\");\n");
525
+ $out .= sprintf("jg.drawLine(%.0f, %.0f, %.0f, %.0f);\n" , 5, $ystartpos , 25, $ystartpos);
526
+ $out .= sprintf("jg.drawStringRect(\"%s\", %.0f, %.0f, 100, \"left\");\n", "Speaker error", 50, $ystartpos - 7);
527
+
528
+ $out .= sprintf("jg.setStroke(1);\n");
529
+ $out .= sprintf("jg.setColor(\"brown\");\n");
530
+ $out .= sprintf("jg.drawLine(%.0f, %.0f, %.0f, %.0f);\n" , 205, $ystartpos , 225, $ystartpos);
531
+ $out .= sprintf("jg.drawLine(%.0f, %.0f, %.0f, %.0f);\n" , 205, $ystartpos -4 , 205, $ystartpos + 4);
532
+ $out .= sprintf("jg.drawLine(%.0f, %.0f, %.0f, %.0f);\n" , 225, $ystartpos -4 , 225, $ystartpos + 4);
533
+ $out .= sprintf("jg.drawStringRect(\"%s\", %.0f, %.0f, 100, \"left\");\n", "Empty Segment", 250, $ystartpos - 7);
534
+
535
+ $ystartpos += 25;
536
+
537
+ $out .= sprintf("jg.setColor(\"#eeffee\");\n");
538
+ $out .= sprintf("jg.fillRect(%.0f, %.0f, %.0f, %.0f);\n", 5, $ystartpos - 3 , 25, 8);
539
+ $out .= sprintf("jg.setColor(\"green\");\n");
540
+ $out .= sprintf("jg.drawStringRect(\"%s\", %.0f, %.0f, 100, \"left\");\n", "References", 50, $ystartpos - 7);
541
+
542
+ $ystartpos += 25;
543
+
544
+ $out .= sprintf("jg.setColor(\"#ffeeee\");\n");
545
+ $out .= sprintf("jg.fillRect(%.0f, %.0f, %.0f, %.0f);\n", 5, $ystartpos - 3 , 25, 8);
546
+ $out .= sprintf("jg.setColor(\"red\");\n");
547
+ $out .= sprintf("jg.drawStringRect(\"%s\", %.0f, %.0f, 100, \"left\");\n", "Systems", 50, $ystartpos - 7);
548
+
549
+ return $out;
550
+ }
551
+
552
+ GetOptions
553
+ (
554
+ 'alignfile=s' => \$AlignFile,
555
+ 'mapfile=s' => \$MapFile,
556
+ 'outputdir=s' => \$Outputdir,
557
+ 'version' => sub { print "align2html version: $VERSION\n"; exit },
558
+ 'help' => sub { usage (); exit },
559
+ );
560
+
561
+ die "ERROR: An Align file must be set." if($AlignFile eq "");
562
+ die "ERROR: An Output directory must be set." if($Outputdir eq "");
563
+
564
+ system("mkdir -p $Outputdir");
565
+
566
+ loadAlignFile($AlignFile);
567
+
568
+ foreach my $SegGrpID ( sort keys %SegGroups )
569
+ {
570
+ my $out = "";
571
+ my $outputfilename = "segmentgroup-$SegGrpID.html";
572
+ my $mySG = $SegGroups{$SegGrpID};
573
+
574
+ $mySG->Compute();
575
+
576
+ $out .= GetHTMLHeader($SegGrpID);
577
+ CalculateMaxScale($mySG->{MINX}, $mySG->{MAXX}, 1, $mySG->{HEIGHT});
578
+ $out .= $mySG->GetFillREFHYP($maxscalewidth);
579
+ $out .= GetDrawScale($mySG->{MINX}, $mySG->{MAXX}, 1, $mySG->{HEIGHT});
580
+ $out .= $mySG->GetSeparationLines($maxscalewidth);
581
+ $out .= $mySG->GetDraw($pixelpersec);
582
+
583
+ foreach (@{ $Alignments{$SegGrpID} })
584
+ {
585
+ my $typ = $_->[0];
586
+ my $tknrefid = $_->[1];
587
+ my $tknhypid = $_->[2];
588
+
589
+ $out .= DrawLinkToken($mySG, $tknrefid, $tknhypid, $mySG->{MINX} - $pixelpersec, $typ);
590
+ }
591
+
592
+ $out .= DrawKey($mySG->{HEIGHT} + 25);
593
+
594
+ $out .= GetHTMLFooter($mySG->{MAXX} - $mySG->{MINX} + $pixelpersec, $mySG->{HEIGHT} + 185, $mySG->{HASFAKETIME}, $mySG);
595
+
596
+ open(FILESG, ">$Outputdir/$outputfilename") or die "Can't open file $Outputdir/$outputfilename for write";
597
+ print FILESG "$out\n";
598
+ close FILESG;
599
+
600
+ my @refspkrs;
601
+ foreach my $segref (sort keys %{ $mySG->{REF} }){ push(@refspkrs, $mySG->{REF}{$segref}->{SPKRID}) if($mySG->{REF}{$segref}->{SPKRID} ne "ref:INTER_SEGMENT_GAP"); }
602
+ my $countSpeakers = scalar unique @refspkrs;
603
+
604
+ my @sysspkrs;
605
+ foreach my $segsys (sort keys %{ $mySG->{SYS} }){ push(@refspkrs, $mySG->{SYS}{$segsys}->{SPKRID}) if(!($mySG->{SYS}{$segsys}->HasOnlyOneFakeToken())); }
606
+ my $counthypSpeakers = scalar unique @sysspkrs;
607
+
608
+ $mySG->{ALIGNED} = 1 if( ($countSpeakers == 0) && ($counthypSpeakers == 0) );
609
+ $mySG->{ALIGNED} = 1 if( ($mySG->{ALIGNED} == 0) && ($countSpeakers == 1) && ($counthypSpeakers == 0) && ($mySG->{HASFAKETIME} == 1) );
610
+
611
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NCORR} = 0 if(!exists($FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NCORR}));
612
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NINS} = 0 if(!exists($FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NINS}));
613
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NSUB} = 0 if(!exists($FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NSUB}));
614
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NDEL} = 0 if(!exists($FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NDEL}));
615
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NREF} = 0 if(!exists($FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NREF}));
616
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NSPKRERR} = 0 if(!exists($FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NSPKRERR}));
617
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{TOTTIME} = 0 if(!exists($FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{TOTTIME}));
618
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{TOTTIMEALIGNED} = 0 if(!exists($FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{TOTTIMEALIGNED}));
619
+
620
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NCORR} += $mySG->{NCORR};
621
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NINS} += $mySG->{NINS};
622
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NSUB} += $mySG->{NSUB};
623
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NDEL} += $mySG->{NDEL};
624
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NREF} += $mySG->{NREF};
625
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{NSPKRERR} += $mySG->{NSPKRERR};
626
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{TOTTIME} += $mySG->{ET} - $mySG->{BT};
627
+ push( @{ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{LISTSG} }, $SegGrpID);
628
+ push( @{ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{LISTSGALIGNED} }, $SegGrpID) if($mySG->{ALIGNED} == 1);
629
+ $FileChannelSG{$mySG->{FILE}}{$mySG->{CHANNEL}}{TOTTIMEALIGNED} += $mySG->{ET} - $mySG->{BT} if($mySG->{ALIGNED} == 1);
630
+
631
+ $Overlap{$countSpeakers}{NREF} = 0 if(!exists($Overlap{$countSpeakers}{NREF}));
632
+ $Overlap{$countSpeakers}{NREF} += $mySG->{NREF};
633
+
634
+ $Overlap{$countSpeakers}{NCORR} = 0 if(!exists($Overlap{$countSpeakers}{NCORR}));
635
+ $Overlap{$countSpeakers}{NCORR} += $mySG->{NCORR};
636
+ $Overlap{$countSpeakers}{PCORR} = "NA";
637
+ $Overlap{$countSpeakers}{PCORR} = sprintf("%.1f", 100*$Overlap{$countSpeakers}{NCORR}/$Overlap{$countSpeakers}{NREF}) if($Overlap{$countSpeakers}{NREF} != 0);
638
+
639
+ $Overlap{$countSpeakers}{NSUB} = 0 if(!exists($Overlap{$countSpeakers}{NSUB}));
640
+ $Overlap{$countSpeakers}{NSUB} += $mySG->{NSUB};
641
+ $Overlap{$countSpeakers}{PSUB} = "NA";
642
+ $Overlap{$countSpeakers}{PSUB} = sprintf("%.1f", 100*$Overlap{$countSpeakers}{NSUB}/$Overlap{$countSpeakers}{NREF}) if($Overlap{$countSpeakers}{NREF} != 0);
643
+
644
+ $Overlap{$countSpeakers}{NINS} = 0 if(!exists($Overlap{$countSpeakers}{NINS}));
645
+ $Overlap{$countSpeakers}{NINS} += $mySG->{NINS};
646
+ $Overlap{$countSpeakers}{PINS} = "NA";
647
+ $Overlap{$countSpeakers}{PINS} = sprintf("%.1f", 100*$Overlap{$countSpeakers}{NINS}/$Overlap{$countSpeakers}{NREF}) if($Overlap{$countSpeakers}{NREF} != 0);
648
+
649
+ $Overlap{$countSpeakers}{NDEL} = 0 if(!exists($Overlap{$countSpeakers}{NDEL}));
650
+ $Overlap{$countSpeakers}{NDEL} += $mySG->{NDEL};
651
+ $Overlap{$countSpeakers}{PDEL} = "NA";
652
+ $Overlap{$countSpeakers}{PDEL} = sprintf("%.1f", 100*$Overlap{$countSpeakers}{NDEL}/$Overlap{$countSpeakers}{NREF}) if($Overlap{$countSpeakers}{NREF} != 0);
653
+
654
+ $Overlap{$countSpeakers}{NSPKRERR} = 0 if(!exists($Overlap{$countSpeakers}{NSPKRERR}));
655
+ $Overlap{$countSpeakers}{NSPKRERR} += $mySG->{NSPKRERR};
656
+ $Overlap{$countSpeakers}{PSPKRERR} = "NA";
657
+ $Overlap{$countSpeakers}{PSPKRERR} = sprintf("%.1f", 100*$Overlap{$countSpeakers}{NSPKRERR}/$Overlap{$countSpeakers}{NREF}) if($Overlap{$countSpeakers}{NREF} != 0);
658
+
659
+ $Overlap{$countSpeakers}{NERR} = $Overlap{$countSpeakers}{NSUB} + $Overlap{$countSpeakers}{NINS} + $Overlap{$countSpeakers}{NDEL} + $Overlap{$countSpeakers}{NSPKRERR};
660
+ $Overlap{$countSpeakers}{PERR} = "NA";
661
+ $Overlap{$countSpeakers}{PERR} = sprintf("%.1f", 100*$Overlap{$countSpeakers}{NERR}/$Overlap{$countSpeakers}{NREF}) if($Overlap{$countSpeakers}{NREF} != 0);
662
+
663
+ $Overlap{$countSpeakers}{TOTTIME} = 0 if(!exists($Overlap{$countSpeakers}{TOTTIME}));
664
+ $Overlap{$countSpeakers}{TOTTIME} += $mySG->{ET} - $mySG->{BT};
665
+
666
+ push( @{ $Overlap{$countSpeakers}{LISTSG} }, $SegGrpID);
667
+ $Overlap{$countSpeakers}{NLISTSG} = scalar @{ $Overlap{$countSpeakers}{LISTSG} };
668
+
669
+ $Overlap{$countSpeakers}{TOTTIMEALIGNED} = 0 if(!exists($Overlap{$countSpeakers}{TOTTIMEALIGNED}));
670
+ $Overlap{$countSpeakers}{TOTTIMEALIGNED} += $mySG->{ET} - $mySG->{BT} if($mySG->{ALIGNED} == 1);
671
+
672
+ push( @{ $Overlap{$countSpeakers}{LISTSGALIGNED} }, $SegGrpID) if($mySG->{ALIGNED} == 1);
673
+ $Overlap{$countSpeakers}{NLISTSGALIGNED} = 0;
674
+ $Overlap{$countSpeakers}{NLISTSGALIGNED} = scalar(@{ $Overlap{$countSpeakers}{LISTSGALIGNED} }) if(exists($Overlap{$countSpeakers}{LISTSGALIGNED}));
675
+
676
+ $Overlap{$countSpeakers}{NUMHYPTOKENS} = 0 if(!exists($Overlap{$countSpeakers}{NUMHYPTOKENS}));
677
+ $Overlap{$countSpeakers}{NUMHYPTOKENS} += $SegGroups{$SegGrpID}->GetNumHypWords();
678
+ }
679
+
680
+ open(FILEINDEX, ">$Outputdir/index.html") or die "$?";
681
+
682
+ print FILEINDEX "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n";
683
+ print FILEINDEX "<html>\n";
684
+ print FILEINDEX "<head>\n";
685
+ print FILEINDEX "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=ISO-8859-1\">\n";
686
+ print FILEINDEX "<title>Overall Performance Summary by Meeting</title>\n";
687
+ print FILEINDEX "</head>\n";
688
+ print FILEINDEX "<body>\n";
689
+ print FILEINDEX "<center>\n";
690
+ print FILEINDEX "<h2>Overall Performance Summary by Meeting</h2>\n";
691
+ print FILEINDEX "<table style=\"text-align: left;\" border=\"1\" cellpadding=\"1\" cellspacing=\"0\">\n";
692
+ print FILEINDEX "<tbody>\n";
693
+ print FILEINDEX "<tr>\n";
694
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: left;\"><b>File\/Channel</b></td>\n";
695
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Regions</b></td>\n";
696
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Total<br>Time</b></td>\n";
697
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Regions<br>Aligned</b></td>\n";
698
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Total Time<br>Aligned</b></td>\n";
699
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Ref Aligned<br>Words</b></td>\n";
700
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Corr</b></td>\n";
701
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Sub</b></td>\n";
702
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Ins</b></td>\n";
703
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Del</b></td>\n";
704
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>SpErr</b></td>\n";
705
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Err</b></td>\n";
706
+ print FILEINDEX "</tr>\n";
707
+
708
+ my $TnbrSG = 0;
709
+ my $Ttottime = 0;
710
+ my $TnbrSGAligned = 0;
711
+ my $Ttottimealigned = 0;
712
+ my $Tnumref = 0;
713
+ my $TpercCorr = 0;
714
+ my $TpercSub = 0;
715
+ my $TpercIns = 0;
716
+ my $TpercDel = 0;
717
+ my $TpercSpErr = 0;
718
+ my $TpercErr = 0;
719
+ my $TnumCorr = 0;
720
+ my $TnumSub = 0;
721
+ my $TnumIns = 0;
722
+ my $TnumDel = 0;
723
+ my $TnumSpErr = 0;
724
+ my $TnumErr = 0;
725
+
726
+ my $ccount = 0;
727
+
728
+ foreach my $file(sort keys %FileChannelSG)
729
+ {
730
+ foreach my $channel(sort keys %{ $FileChannelSG{$file} })
731
+ {
732
+ my $cleanfile = $file;
733
+ $cleanfile =~ s/\//\_/g;
734
+ my $filename = "$cleanfile" . "_" . "$channel" . ".html";
735
+
736
+ my $percCorr = "NA";
737
+ my $percSub = "NA";
738
+ my $percIns = "NA";
739
+ my $percDel = "NA";
740
+ my $percErr = "NA";
741
+ my $percSpErr = "NA";
742
+
743
+ my $numref = $FileChannelSG{$file}{$channel}{NREF};
744
+ $Tnumref += $numref;
745
+
746
+ my $nbrSG = scalar(@{ $FileChannelSG{$file}{$channel}{LISTSG} });
747
+ $TnbrSG += $nbrSG;
748
+
749
+ my $tottime = sprintf("%.3f", $FileChannelSG{$file}{$channel}{TOTTIME});
750
+ $Ttottime += $tottime;
751
+
752
+ my $nbrSGAligned = scalar(@{ $FileChannelSG{$file}{$channel}{LISTSGALIGNED} });
753
+ $TnbrSGAligned += $nbrSGAligned;
754
+
755
+ my $tottimealigned = sprintf("%.3f", $FileChannelSG{$file}{$channel}{TOTTIMEALIGNED});
756
+ $Ttottimealigned += $tottimealigned;
757
+
758
+ if($FileChannelSG{$file}{$channel}{NREF} != 0)
759
+ {
760
+ $percCorr = sprintf("%.1f%% (%d)", 100*$FileChannelSG{$file}{$channel}{NCORR}/$FileChannelSG{$file}{$channel}{NREF}, $FileChannelSG{$file}{$channel}{NCORR});
761
+ $percSub = sprintf("%.1f%% (%d)", 100*$FileChannelSG{$file}{$channel}{NSUB}/$FileChannelSG{$file}{$channel}{NREF}, $FileChannelSG{$file}{$channel}{NSUB});
762
+ $percIns = sprintf("%.1f%% (%d)", 100*$FileChannelSG{$file}{$channel}{NINS}/$FileChannelSG{$file}{$channel}{NREF}, $FileChannelSG{$file}{$channel}{NINS});
763
+ $percDel = sprintf("%.1f%% (%d)", 100*$FileChannelSG{$file}{$channel}{NDEL}/$FileChannelSG{$file}{$channel}{NREF}, $FileChannelSG{$file}{$channel}{NDEL});
764
+ $percErr = sprintf("%.1f%% (%d)", 100*($FileChannelSG{$file}{$channel}{NDEL}+$FileChannelSG{$file}{$channel}{NINS}+$FileChannelSG{$file}{$channel}{NSUB}+$FileChannelSG{$file}{$channel}{NSPKRERR})/$FileChannelSG{$file}{$channel}{NREF}, $FileChannelSG{$file}{$channel}{NDEL}+$FileChannelSG{$file}{$channel}{NINS}+$FileChannelSG{$file}{$channel}{NSUB}+$FileChannelSG{$file}{$channel}{NSPKRERR});
765
+ $percSpErr = sprintf("%.1f%% (%d)", 100*$FileChannelSG{$file}{$channel}{NSPKRERR}/$FileChannelSG{$file}{$channel}{NREF}, $FileChannelSG{$file}{$channel}{NSPKRERR});
766
+
767
+ $TpercCorr += sprintf("%.3f", 100*$FileChannelSG{$file}{$channel}{NCORR}/$FileChannelSG{$file}{$channel}{NREF});
768
+ $TpercSub += sprintf("%.3f", 100*$FileChannelSG{$file}{$channel}{NSUB}/$FileChannelSG{$file}{$channel}{NREF});
769
+ $TpercIns += sprintf("%.3f", 100*$FileChannelSG{$file}{$channel}{NINS}/$FileChannelSG{$file}{$channel}{NREF});
770
+ $TpercDel += sprintf("%.3f", 100*$FileChannelSG{$file}{$channel}{NDEL}/$FileChannelSG{$file}{$channel}{NREF});
771
+ $TpercSpErr += sprintf("%.3f", 100*$FileChannelSG{$file}{$channel}{NSPKRERR}/$FileChannelSG{$file}{$channel}{NREF});
772
+ $TpercErr += sprintf("%.3f", 100*($FileChannelSG{$file}{$channel}{NDEL}+$FileChannelSG{$file}{$channel}{NINS}+$FileChannelSG{$file}{$channel}{NSUB}+$FileChannelSG{$file}{$channel}{NSPKRERR})/$FileChannelSG{$file}{$channel}{NREF});
773
+ $TnumCorr += $FileChannelSG{$file}{$channel}{NCORR};
774
+ $TnumSub += $FileChannelSG{$file}{$channel}{NSUB};
775
+ $TnumIns += $FileChannelSG{$file}{$channel}{NINS};
776
+ $TnumDel += $FileChannelSG{$file}{$channel}{NDEL};
777
+ $TnumSpErr += $FileChannelSG{$file}{$channel}{NSPKRERR};
778
+ $TnumErr += $FileChannelSG{$file}{$channel}{NDEL}+$FileChannelSG{$file}{$channel}{NINS}+$FileChannelSG{$file}{$channel}{NSUB}+$FileChannelSG{$file}{$channel}{NSPKRERR};
779
+
780
+ $ccount++;
781
+ }
782
+
783
+ print FILEINDEX "<tr>\n";
784
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: left;\"><a href=\"$filename\" target=\"_blank\">$file\/$channel</a></td>\n";
785
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$nbrSG</td>\n";
786
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$tottime</td>\n";
787
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$nbrSGAligned</td>\n";
788
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$tottimealigned</td>\n";
789
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$numref</td>\n";
790
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$percCorr</td>\n";
791
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$percSub</td>\n";
792
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$percIns</td>\n";
793
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$percDel</td>\n";
794
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$percSpErr</td>\n";
795
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$percErr</td>\n";
796
+ print FILEINDEX "</tr>\n";
797
+ }
798
+ }
799
+
800
+ my $dTpercCorr = sprintf("%.1f%% (%d)", 100*$TnumCorr/$Tnumref, $TnumCorr);
801
+ my $dTpercSub = sprintf("%.1f%% (%d)", 100*$TnumSub/$Tnumref, $TnumSub);
802
+ my $dTpercIns = sprintf("%.1f%% (%d)", 100*$TnumIns/$Tnumref, $TnumIns);
803
+ my $dTpercDel = sprintf("%.1f%% (%d)", 100*$TnumDel/$Tnumref, $TnumDel);
804
+ my $dTpercSpErr = sprintf("%.1f%% (%d)", 100*$TnumSpErr/$Tnumref, $TnumSpErr);
805
+ my $dTpercErr = sprintf("%.1f%% (%d)", 100*$TnumErr/$Tnumref, $TnumErr);
806
+
807
+ print FILEINDEX "<tr>\n";
808
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: left;\"><b>Ensemble</b></td>\n";
809
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$TnbrSG</td>\n";
810
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$Ttottime</td>\n";
811
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$TnbrSGAligned</td>\n";
812
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$Ttottimealigned</td>\n";
813
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$Tnumref</td>\n";
814
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$dTpercCorr</td>\n";
815
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$dTpercSub</td>\n";
816
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$dTpercIns</td>\n";
817
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$dTpercDel</td>\n";
818
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$dTpercSpErr</td>\n";
819
+ print FILEINDEX "<td style=\"vertical-align: top; text-align: center;\">$dTpercErr</td>\n";
820
+ print FILEINDEX "</tr>\n";
821
+ print FILEINDEX "</tbody>\n";
822
+ print FILEINDEX "</table>\n";
823
+
824
+ print FILEINDEX "<br>\n";
825
+
826
+ my $Total_regs = 0;
827
+ my $Total_tottime = 0;
828
+ my $Total_regsalign = 0;
829
+ my $Total_tottimealign = 0;
830
+ my $Total_nref = 0;
831
+ my $Total_ncorr = 0;
832
+ my $Total_nsub = 0;
833
+ my $Total_nins = 0;
834
+ my $Total_ndel = 0;
835
+ my $Total_nspkerr = 0;
836
+ my $Total_nerr = 0;
837
+
838
+ print FILEINDEX "<table style=\"text-align: left;\" border=\"1\" cellpadding=\"1\" cellspacing=\"0\">\n";
839
+ print FILEINDEX "<tbody>\n";
840
+ print FILEINDEX "<tr>\n";
841
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Ref Speaker<br>Overlap</b></td>\n";
842
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Regions</b></td>\n";
843
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Total<br>Time</b></td>\n";
844
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Regions<br>Aligned</b></td>\n";
845
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Total Time<br>Aligned</b></td>\n";
846
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Ref Aligned<br>Words</b></td>\n";
847
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Corr</b></td>\n";
848
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Sub</b></td>\n";
849
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Ins</b></td>\n";
850
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Del</b></td>\n";
851
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>SpErr</b></td>\n";
852
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Err</b></td>\n";
853
+ print FILEINDEX "</tr>\n";
854
+
855
+ foreach my $spkover (sort {$a <=> $b} keys %Overlap)
856
+ {
857
+ my $display_regs = $Overlap{$spkover}{NLISTSG};
858
+ my $display_tottime = sprintf("%.3f", $Overlap{$spkover}{TOTTIME});
859
+ my $display_regsalign = $Overlap{$spkover}{NLISTSGALIGNED};
860
+ my $display_tottimealign = sprintf("%.3f", $Overlap{$spkover}{TOTTIMEALIGNED});
861
+ my $display_nref = "-";
862
+ my $display_ncorr = "-";
863
+ my $display_nsub = "-";
864
+ my $display_nins = "-";
865
+ my $display_ndel = "-";
866
+ my $display_nspkerr = "-";
867
+ my $display_nerr = "-";
868
+
869
+ $Total_regs += $Overlap{$spkover}{NLISTSG};
870
+ $Total_tottime += $Overlap{$spkover}{TOTTIME};
871
+ $Total_regsalign += $Overlap{$spkover}{NLISTSGALIGNED};
872
+ $Total_tottimealign += $Overlap{$spkover}{TOTTIMEALIGNED};
873
+
874
+ if($spkover == 0)
875
+ {
876
+ $display_nins = sprintf("(%d)", $Overlap{$spkover}{NUMHYPTOKENS});
877
+
878
+ $Total_nins += $Overlap{$spkover}{NUMHYPTOKENS};
879
+ $Total_nerr += $Total_nins;
880
+ }
881
+
882
+ if($Overlap{$spkover}{NREF} != 0)
883
+ {
884
+ $display_nref = $Overlap{$spkover}{NREF};
885
+ $display_ncorr = sprintf("%.1f%% (%d)", $Overlap{$spkover}{PCORR}, $Overlap{$spkover}{NCORR});
886
+ $display_nsub = sprintf("%.1f%% (%d)", $Overlap{$spkover}{PSUB}, $Overlap{$spkover}{NSUB});
887
+ $display_nins = sprintf("%.1f%% (%d)", $Overlap{$spkover}{PINS}, $Overlap{$spkover}{NINS});
888
+ $display_ndel = sprintf("%.1f%% (%d)", $Overlap{$spkover}{PDEL}, $Overlap{$spkover}{NDEL});
889
+ $display_nspkerr = sprintf("%.1f%% (%d)", $Overlap{$spkover}{PSPKRERR}, $Overlap{$spkover}{NSPKRERR});
890
+ $display_nerr = sprintf("%.1f%% (%d)", $Overlap{$spkover}{PERR}, $Overlap{$spkover}{NERR});
891
+
892
+ $Total_nref += $Overlap{$spkover}{NREF};
893
+ $Total_ncorr += $Overlap{$spkover}{NCORR};
894
+ $Total_nsub += $Overlap{$spkover}{NSUB};
895
+ $Total_nins += $Overlap{$spkover}{NINS};
896
+ $Total_ndel += $Overlap{$spkover}{NDEL};
897
+ $Total_nspkerr += $Overlap{$spkover}{NSPKRERR};
898
+ $Total_nerr += $Overlap{$spkover}{NERR};
899
+ }
900
+
901
+ print FILEINDEX "<tr>\n";
902
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>$spkover<b></td>\n";
903
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_regs</td>\n";
904
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_tottime</td>\n";
905
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_regsalign</td>\n";
906
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_tottimealign</td>\n";
907
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nref</td>\n";
908
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_ncorr</td>\n";
909
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nsub</td>\n";
910
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nins</td>\n";
911
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_ndel</td>\n";
912
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nspkerr</td>\n";
913
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nerr</td>\n";
914
+ print FILEINDEX "</tr>\n";
915
+
916
+ # data for Cumuloverlap table
917
+ $CumulOverlap{$spkover}{NLISTSG} = $Total_regs;
918
+ $CumulOverlap{$spkover}{TOTTIME} = $Total_tottime;
919
+ $CumulOverlap{$spkover}{NLISTSGALIGNED} = $Total_regsalign;
920
+ $CumulOverlap{$spkover}{TOTTIMEALIGNED} = $Total_tottimealign;
921
+ $CumulOverlap{$spkover}{NREF} = $Total_nref;
922
+ $CumulOverlap{$spkover}{NCORR} = $Total_ncorr;
923
+ $CumulOverlap{$spkover}{NSUB} = $Total_nsub;
924
+ $CumulOverlap{$spkover}{NINS} = $Total_nins;
925
+ $CumulOverlap{$spkover}{NDEL} = $Total_ndel;
926
+ $CumulOverlap{$spkover}{NSPKRERR} = $Total_nspkerr;
927
+ $CumulOverlap{$spkover}{NERR} = $Total_nerr;
928
+ }
929
+
930
+ my $display_Total_regs = $Total_regs;
931
+ my $display_Total_tottime = sprintf("%.3f", $Total_tottime);
932
+ my $display_Total_regsalign = $Total_regsalign;
933
+ my $display_Total_tottimealign = sprintf("%.3f", $Total_tottimealign);
934
+ my $display_Total_nref = $Total_nref;
935
+ my $display_Total_ncorr = sprintf("%.1f%% (%d)", 100*$Total_ncorr/$Total_nref, $Total_ncorr);
936
+ my $display_Total_nsub = sprintf("%.1f%% (%d)", 100*$Total_nsub/$Total_nref, $Total_nsub);
937
+ my $display_Total_nins = sprintf("%.1f%% (%d)", 100*$Total_nins/$Total_nref, $Total_nins);
938
+ my $display_Total_ndel = sprintf("%.1f%% (%d)", 100*$Total_ndel/$Total_nref, $Total_ndel);
939
+ my $display_Total_nspkerr = sprintf("%.1f%% (%d)", 100*$Total_nspkerr/$Total_nref, $Total_nspkerr);
940
+ my $display_Total_nerr = sprintf("%.1f%% (%d)", 100*$Total_nerr/$Total_nref, $Total_nerr);
941
+
942
+ print FILEINDEX "<tr>\n";
943
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Ensemble</b></td>\n";
944
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_regs</td>\n";
945
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_tottime</td>\n";
946
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_regsalign</td>\n";
947
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_tottimealign</td>\n";
948
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_nref</td>\n";
949
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_ncorr</td>\n";
950
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_nsub</td>\n";
951
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_nins</td>\n";
952
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_ndel</td>\n";
953
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_nspkerr</td>\n";
954
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_nerr</td>\n";
955
+ print FILEINDEX "</tr>\n";
956
+
957
+ print FILEINDEX "</tbody>\n";
958
+ print FILEINDEX "</table>\n";
959
+
960
+ print FILEINDEX "<br>\n";
961
+
962
+ print FILEINDEX "<table style=\"text-align: left;\" border=\"1\" cellpadding=\"1\" cellspacing=\"0\">\n";
963
+ print FILEINDEX "<tbody>\n";
964
+ print FILEINDEX "<tr>\n";
965
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Ref Speaker<br>Cumulative<br>Overlap</b></td>\n";
966
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Regions</b></td>\n";
967
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Total<br>Time</b></td>\n";
968
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Regions<br>Aligned</b></td>\n";
969
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Total Time<br>Aligned</b></td>\n";
970
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Ref Aligned<br>Words</b></td>\n";
971
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Corr</b></td>\n";
972
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Sub</b></td>\n";
973
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Ins</b></td>\n";
974
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Del</b></td>\n";
975
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>SpErr</b></td>\n";
976
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Err</b></td>\n";
977
+ print FILEINDEX "</tr>\n";
978
+
979
+ foreach my $cumulspkover (sort {$a <=> $b} keys %CumulOverlap)
980
+ {
981
+ my $display_regs = $CumulOverlap{$cumulspkover}{NLISTSG};
982
+ my $display_tottime = sprintf("%.3f", $CumulOverlap{$cumulspkover}{TOTTIME});
983
+ my $display_regsalign = $CumulOverlap{$cumulspkover}{NLISTSGALIGNED};
984
+ my $display_tottimealign = sprintf("%.3f", $CumulOverlap{$cumulspkover}{TOTTIMEALIGNED});
985
+ my $display_nref = "-";
986
+ my $display_ncorr = "-";
987
+ my $display_nsub = "-";
988
+ my $display_nins = "-";
989
+ my $display_ndel = "-";
990
+ my $display_nspkerr = "-";
991
+ my $display_nerr = "-";
992
+
993
+ if($cumulspkover == 0)
994
+ {
995
+ $display_nins = sprintf("(%d)", $CumulOverlap{$cumulspkover}{NINS});
996
+ }
997
+
998
+ if($CumulOverlap{$cumulspkover}{NREF} != 0)
999
+ {
1000
+ $display_nref = $CumulOverlap{$cumulspkover}{NREF};
1001
+ $display_ncorr = sprintf("%.1f%% (%d)", $CumulOverlap{$cumulspkover}{NCORR} *100/$CumulOverlap{$cumulspkover}{NREF}, $CumulOverlap{$cumulspkover}{NCORR});
1002
+ $display_nsub = sprintf("%.1f%% (%d)", $CumulOverlap{$cumulspkover}{NSUB} *100/$CumulOverlap{$cumulspkover}{NREF}, $CumulOverlap{$cumulspkover}{NSUB});
1003
+ $display_nins = sprintf("%.1f%% (%d)", $CumulOverlap{$cumulspkover}{NINS} *100/$CumulOverlap{$cumulspkover}{NREF}, $CumulOverlap{$cumulspkover}{NINS});
1004
+ $display_ndel = sprintf("%.1f%% (%d)", $CumulOverlap{$cumulspkover}{NDEL} *100/$CumulOverlap{$cumulspkover}{NREF}, $CumulOverlap{$cumulspkover}{NDEL});
1005
+ $display_nspkerr = sprintf("%.1f%% (%d)", $CumulOverlap{$cumulspkover}{NSPKRERR}*100/$CumulOverlap{$cumulspkover}{NREF}, $CumulOverlap{$cumulspkover}{NSPKRERR});
1006
+ $display_nerr = sprintf("%.1f%% (%d)", $CumulOverlap{$cumulspkover}{NERR} *100/$CumulOverlap{$cumulspkover}{NREF}, $CumulOverlap{$cumulspkover}{NERR});
1007
+ }
1008
+
1009
+ print FILEINDEX "<tr>\n";
1010
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>$cumulspkover<b></td>\n";
1011
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_regs</td>\n";
1012
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_tottime</td>\n";
1013
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_regsalign</td>\n";
1014
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_tottimealign</td>\n";
1015
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nref</td>\n";
1016
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_ncorr</td>\n";
1017
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nsub</td>\n";
1018
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nins</td>\n";
1019
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_ndel</td>\n";
1020
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nspkerr</td>\n";
1021
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nerr</td>\n";
1022
+ print FILEINDEX "</tr>\n";
1023
+ }
1024
+
1025
+
1026
+ print FILEINDEX "</tbody>\n";
1027
+ print FILEINDEX "</table>\n";
1028
+
1029
+
1030
+ print FILEINDEX "</center>\n";
1031
+ print FILEINDEX "</body>\n";
1032
+ print FILEINDEX "</html>\n";
1033
+
1034
+ close FILEINDEX;
1035
+
1036
+ foreach my $file(sort keys %FileChannelSG)
1037
+ {
1038
+ foreach my $channel(sort keys %{ $FileChannelSG{$file} })
1039
+ {
1040
+ my %overallmeeting;
1041
+ my %cumuloverallmeeting;
1042
+ my $cleanfile = $file;
1043
+ $cleanfile =~ s/\//\_/g;
1044
+ my $filename = "$cleanfile" . "_" . "$channel" . ".html";
1045
+ my $bottom = "";
1046
+
1047
+ open(FILEINDEX, ">$Outputdir/$filename") or die "$?";
1048
+
1049
+ print FILEINDEX "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n";
1050
+ print FILEINDEX "<html>\n";
1051
+ print FILEINDEX "<head>\n";
1052
+ print FILEINDEX "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=ISO-8859-1\">\n";
1053
+ print FILEINDEX "<title>Overall Performance Summary for Meeting $file\/$channel</title>\n";
1054
+ print FILEINDEX "</head>\n";
1055
+ print FILEINDEX "<body>\n";
1056
+
1057
+ print FILEINDEX "<center>\n";
1058
+ print FILEINDEX "<h2>Overall Performance Summary for Meeting $file\/$channel</h2>\n";
1059
+ print FILEINDEX "<table style=\"text-align: left;\" border=\"1\" cellpadding=\"1\" cellspacing=\"0\">\n";
1060
+ print FILEINDEX "<tbody>\n";
1061
+
1062
+ print FILEINDEX "<tr>\n";
1063
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: left;\"><b>Region ID</b></b></td>\n";
1064
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Begin<br>Time</td>\n";
1065
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>End<br>Time</b></td>\n";
1066
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Duration</b></td>\n";
1067
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Ref<br>Speaker</b></td>\n";
1068
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Hyp<br>Speaker</b></td>\n";
1069
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Ref Aligned<br>Words</b></td>\n";
1070
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Corr</b></td>\n";
1071
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Sub</b></td>\n";
1072
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Ins</b></td>\n";
1073
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Del</b></td>\n";
1074
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>SpErr</b></td>\n";
1075
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Err</b></td>\n";
1076
+ print FILEINDEX "</tr>\n";
1077
+
1078
+ foreach my $SG_ID (sort {$a <=> $b} @{ $FileChannelSG{$file}{$channel}{LISTSG} })
1079
+ {
1080
+ my $BT = sprintf("%.3f", $SegGroups{$SG_ID}->{BT});
1081
+ my $ET = sprintf("%.3f", $SegGroups{$SG_ID}->{ET});
1082
+ my $Duration = sprintf("%.3f", $SegGroups{$SG_ID}->{ET} - $SegGroups{$SG_ID}->{BT});
1083
+
1084
+ my @refspkrs;
1085
+ my @sysspkrs;
1086
+
1087
+ foreach my $segref (sort keys %{ $SegGroups{$SG_ID}->{REF} }) { push(@refspkrs, $SegGroups{$SG_ID}->{REF}{$segref}->{SPKRID}) if($SegGroups{$SG_ID}->{REF}{$segref}->{SPKRID} ne "ref:INTER_SEGMENT_GAP"); }
1088
+ foreach my $segsys (sort keys %{ $SegGroups{$SG_ID}->{SYS} }) { push(@sysspkrs, $SegGroups{$SG_ID}->{SYS}{$segsys}->{SPKRID}) if(!($SegGroups{$SG_ID}->{SYS}{$segsys}->HasOnlyOneFakeToken())); }
1089
+
1090
+ my $nrefspkr = scalar unique @refspkrs;
1091
+ my $nhypspkr = scalar unique @sysspkrs;
1092
+
1093
+ $SegGroups{$SG_ID}->{ALIGNED} = 1 if( ($nrefspkr == 0) && ($nhypspkr == 0) );
1094
+ $SegGroups{$SG_ID}->{ALIGNED} = 1 if( ($SegGroups{$SG_ID}->{ALIGNED} == 0) && ($nrefspkr == 1) && ($nhypspkr == 0) && ($SegGroups{$SG_ID}->{HASFAKETIME} == 1) );
1095
+
1096
+ my $titleSG = "<a href=\"segmentgroup-$SG_ID.html\" target=\"_blank\">$SG_ID</a>";
1097
+ my $nref = "-";
1098
+ my $percCorr = "-";
1099
+ my $percSub = "-";
1100
+ my $percIns = "-";
1101
+ my $percDel = "-";
1102
+ my $percErr = "-";
1103
+ my $percSpErr = "-";
1104
+
1105
+ if($SegGroups{$SG_ID}->{NREF} != 0)
1106
+ {
1107
+ $percCorr = sprintf("%.1f%% (%d)", 100*$SegGroups{$SG_ID}->{NCORR}/$SegGroups{$SG_ID}->{NREF}, $SegGroups{$SG_ID}->{NCORR});
1108
+ $percSub = sprintf("%.1f%% (%d)", 100*$SegGroups{$SG_ID}->{NSUB}/$SegGroups{$SG_ID}->{NREF}, $SegGroups{$SG_ID}->{NSUB});
1109
+ $percIns = sprintf("%.1f%% (%d)", 100*$SegGroups{$SG_ID}->{NINS}/$SegGroups{$SG_ID}->{NREF}, $SegGroups{$SG_ID}->{NINS});
1110
+ $percDel = sprintf("%.1f%% (%d)", 100*$SegGroups{$SG_ID}->{NDEL}/$SegGroups{$SG_ID}->{NREF}, $SegGroups{$SG_ID}->{NDEL});
1111
+ $percErr = sprintf("%.1f%% (%d)", 100*($SegGroups{$SG_ID}->{NDEL}+$SegGroups{$SG_ID}->{NINS}+$SegGroups{$SG_ID}->{NSUB}+$SegGroups{$SG_ID}->{NSPKRERR})/$SegGroups{$SG_ID}->{NREF}, $SegGroups{$SG_ID}->{NDEL}+$SegGroups{$SG_ID}->{NINS}+$SegGroups{$SG_ID}->{NSUB}+$SegGroups{$SG_ID}->{NSPKRERR});
1112
+ $percSpErr = sprintf("%.1f%% (%d)", 100*$SegGroups{$SG_ID}->{NSPKRERR}/$SegGroups{$SG_ID}->{NREF}, $SegGroups{$SG_ID}->{NSPKRERR});
1113
+ }
1114
+ else
1115
+ {
1116
+ $percIns = sprintf("(%d)", $SegGroups{$SG_ID}->{NINS}) if($SegGroups{$SG_ID}->{ALIGNED} == 1);
1117
+ }
1118
+
1119
+ if($SegGroups{$SG_ID}->{ALIGNED} == 0)
1120
+ {
1121
+ $titleSG = "*<i>$titleSG</i>";
1122
+ $nrefspkr = "<i>$nrefspkr</i>";
1123
+ $nhypspkr = "<i>$nhypspkr</i>";
1124
+ $BT = "<i>$BT</i>";
1125
+ $ET = "<i>$ET</i>";
1126
+ $Duration = "<i>$Duration</i>";
1127
+ $bottom = "<br>*: Segment Group ignored for scoring.<br>";
1128
+ }
1129
+ else
1130
+ {
1131
+ $nref = $SegGroups{$SG_ID}->{NREF};
1132
+ }
1133
+
1134
+ print FILEINDEX "<tr>\n";
1135
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: left;\">$titleSG</td>\n";
1136
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$BT</td>\n";
1137
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$ET</td>\n";
1138
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$Duration</td>\n";
1139
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$nrefspkr</td>\n";
1140
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$nhypspkr</td>\n";
1141
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$nref</td>\n";
1142
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$percCorr</td>\n";
1143
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$percSub</td>\n";
1144
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$percIns</td>\n";
1145
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$percDel</td>\n";
1146
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$percSpErr</td>\n";
1147
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$percErr</td>\n";
1148
+ print FILEINDEX "</tr>\n";
1149
+
1150
+ $BT =~ s/<i>//;
1151
+ $ET =~ s/<i>//;
1152
+ $nrefspkr =~ s/<i>//;
1153
+ $nhypspkr =~ s/<i>//;
1154
+ $BT =~ s/<\/i>//;
1155
+ $ET =~ s/<\/i>//;
1156
+ $nrefspkr =~ s/<\/i>//;
1157
+ $nhypspkr =~ s/<\/i>//;
1158
+
1159
+ my $countSpeakers = $nrefspkr;
1160
+
1161
+ $overallmeeting{$countSpeakers}{NREF} = 0 if(!exists($overallmeeting{$countSpeakers}{NREF}));
1162
+ $overallmeeting{$countSpeakers}{NREF} += $SegGroups{$SG_ID}->{NREF};
1163
+
1164
+ $overallmeeting{$countSpeakers}{NCORR} = 0 if(!exists($overallmeeting{$countSpeakers}{NCORR}));
1165
+ $overallmeeting{$countSpeakers}{NCORR} += $SegGroups{$SG_ID}->{NCORR};
1166
+ $overallmeeting{$countSpeakers}{PCORR} = "NA";
1167
+ $overallmeeting{$countSpeakers}{PCORR} = sprintf("%.1f", 100*$overallmeeting{$countSpeakers}{NCORR}/$overallmeeting{$countSpeakers}{NREF}) if($overallmeeting{$countSpeakers}{NREF} != 0);
1168
+
1169
+ $overallmeeting{$countSpeakers}{NSUB} = 0 if(!exists($overallmeeting{$countSpeakers}{NSUB}));
1170
+ $overallmeeting{$countSpeakers}{NSUB} += $SegGroups{$SG_ID}->{NSUB};
1171
+ $overallmeeting{$countSpeakers}{PSUB} = "NA";
1172
+ $overallmeeting{$countSpeakers}{PSUB} = sprintf("%.1f", 100*$overallmeeting{$countSpeakers}{NSUB}/$overallmeeting{$countSpeakers}{NREF}) if($overallmeeting{$countSpeakers}{NREF} != 0);
1173
+
1174
+ $overallmeeting{$countSpeakers}{NINS} = 0 if(!exists($overallmeeting{$countSpeakers}{NINS}));
1175
+ $overallmeeting{$countSpeakers}{NINS} += $SegGroups{$SG_ID}->{NINS};
1176
+ $overallmeeting{$countSpeakers}{PINS} = "NA";
1177
+ $overallmeeting{$countSpeakers}{PINS} = sprintf("%.1f", 100*$overallmeeting{$countSpeakers}{NINS}/$overallmeeting{$countSpeakers}{NREF}) if($overallmeeting{$countSpeakers}{NREF} != 0);
1178
+
1179
+ $overallmeeting{$countSpeakers}{NDEL} = 0 if(!exists($overallmeeting{$countSpeakers}{NDEL}));
1180
+ $overallmeeting{$countSpeakers}{NDEL} += $SegGroups{$SG_ID}->{NDEL};
1181
+ $overallmeeting{$countSpeakers}{PDEL} = "NA";
1182
+ $overallmeeting{$countSpeakers}{PDEL} = sprintf("%.1f", 100*$overallmeeting{$countSpeakers}{NDEL}/$overallmeeting{$countSpeakers}{NREF}) if($overallmeeting{$countSpeakers}{NREF} != 0);
1183
+
1184
+ $overallmeeting{$countSpeakers}{NSPKRERR} = 0 if(!exists($overallmeeting{$countSpeakers}{NSPKRERR}));
1185
+ $overallmeeting{$countSpeakers}{NSPKRERR} += $SegGroups{$SG_ID}->{NSPKRERR};
1186
+ $overallmeeting{$countSpeakers}{PSPKRERR} = "NA";
1187
+ $overallmeeting{$countSpeakers}{PSPKRERR} = sprintf("%.1f", 100*$overallmeeting{$countSpeakers}{NSPKRERR}/$overallmeeting{$countSpeakers}{NREF}) if($overallmeeting{$countSpeakers}{NREF} != 0);
1188
+
1189
+ $overallmeeting{$countSpeakers}{NERR} = $overallmeeting{$countSpeakers}{NSUB} + $overallmeeting{$countSpeakers}{NINS} + $overallmeeting{$countSpeakers}{NDEL} + $overallmeeting{$countSpeakers}{NSPKRERR};
1190
+ $overallmeeting{$countSpeakers}{PERR} = "NA";
1191
+ $overallmeeting{$countSpeakers}{PERR} = sprintf("%.1f", 100*$overallmeeting{$countSpeakers}{NERR}/$overallmeeting{$countSpeakers}{NREF}) if($overallmeeting{$countSpeakers}{NREF} != 0);
1192
+
1193
+ $overallmeeting{$countSpeakers}{TOTTIME} = 0 if(!exists($overallmeeting{$countSpeakers}{TOTTIME}));
1194
+ $overallmeeting{$countSpeakers}{TOTTIME} += $SegGroups{$SG_ID}->{ET} - $SegGroups{$SG_ID}->{BT};
1195
+
1196
+ push( @{ $overallmeeting{$countSpeakers}{LISTSG} }, $SG_ID);
1197
+ $overallmeeting{$countSpeakers}{NLISTSG} = scalar @{ $overallmeeting{$countSpeakers}{LISTSG} };
1198
+
1199
+ $overallmeeting{$countSpeakers}{TOTTIMEALIGNED} = 0 if(!exists($overallmeeting{$countSpeakers}{TOTTIMEALIGNED}));
1200
+ $overallmeeting{$countSpeakers}{TOTTIMEALIGNED} += $SegGroups{$SG_ID}->{ET} - $SegGroups{$SG_ID}->{BT} if($SegGroups{$SG_ID}->{ALIGNED} == 1);
1201
+
1202
+ push( @{ $overallmeeting{$countSpeakers}{LISTSGALIGNED} }, $SG_ID) if($SegGroups{$SG_ID}->{ALIGNED} == 1);
1203
+ $overallmeeting{$countSpeakers}{NLISTSGALIGNED} = 0;
1204
+ $overallmeeting{$countSpeakers}{NLISTSGALIGNED} = scalar(@{ $overallmeeting{$countSpeakers}{LISTSGALIGNED} }) if(exists($overallmeeting{$countSpeakers}{LISTSGALIGNED}));
1205
+
1206
+ $overallmeeting{$countSpeakers}{NUMHYPTOKENS} = 0 if(!exists($overallmeeting{$countSpeakers}{NUMHYPTOKENS}));
1207
+ $overallmeeting{$countSpeakers}{NUMHYPTOKENS} += $SegGroups{$SG_ID}->GetNumHypWords();
1208
+ }
1209
+
1210
+ print FILEINDEX "</tbody>\n";
1211
+ print FILEINDEX "</table>\n";
1212
+ print FILEINDEX "$bottom";
1213
+ print FILEINDEX "<br>\n";
1214
+
1215
+ my $Total_regs = 0;
1216
+ my $Total_tottime = 0;
1217
+ my $Total_regsalign = 0;
1218
+ my $Total_tottimealign = 0;
1219
+ my $Total_nref = 0;
1220
+ my $Total_ncorr = 0;
1221
+ my $Total_nsub = 0;
1222
+ my $Total_nins = 0;
1223
+ my $Total_ndel = 0;
1224
+ my $Total_nspkerr = 0;
1225
+ my $Total_nerr = 0;
1226
+
1227
+ print FILEINDEX "<table style=\"text-align: left;\" border=\"1\" cellpadding=\"1\" cellspacing=\"0\">\n";
1228
+ print FILEINDEX "<tbody>\n";
1229
+ print FILEINDEX "<tr>\n";
1230
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Ref Speaker<br>Overlap</b></td>\n";
1231
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Regions</b></td>\n";
1232
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Total<br>Time</b></td>\n";
1233
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Regions<br>Aligned</b></td>\n";
1234
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Total Time<br>Aligned</b></td>\n";
1235
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Ref Aligned<br>Words</b></td>\n";
1236
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Corr</b></td>\n";
1237
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Sub</b></td>\n";
1238
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Ins</b></td>\n";
1239
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Del</b></td>\n";
1240
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>SpErr</b></td>\n";
1241
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Err</b></td>\n";
1242
+ print FILEINDEX "</tr>\n";
1243
+
1244
+ foreach my $spkover (sort {$a <=> $b} keys %overallmeeting)
1245
+ {
1246
+ my $display_regs = $overallmeeting{$spkover}{NLISTSG};
1247
+ my $display_tottime = sprintf("%.3f", $overallmeeting{$spkover}{TOTTIME});
1248
+ my $display_regsalign = $overallmeeting{$spkover}{NLISTSGALIGNED};
1249
+ my $display_tottimealign = sprintf("%.3f", $overallmeeting{$spkover}{TOTTIMEALIGNED});
1250
+ my $display_nref = "-";
1251
+ my $display_ncorr = "-";
1252
+ my $display_nsub = "-";
1253
+ my $display_nins = "-";
1254
+ my $display_ndel = "-";
1255
+ my $display_nspkerr = "-";
1256
+ my $display_nerr = "-";
1257
+
1258
+ $Total_regs += $overallmeeting{$spkover}{NLISTSG};
1259
+ $Total_tottime += $overallmeeting{$spkover}{TOTTIME};
1260
+ $Total_regsalign += $overallmeeting{$spkover}{NLISTSGALIGNED};
1261
+ $Total_tottimealign += $overallmeeting{$spkover}{TOTTIMEALIGNED};
1262
+
1263
+ if($spkover == 0)
1264
+ {
1265
+ $display_nins = sprintf("(%d)", $overallmeeting{$spkover}{NUMHYPTOKENS});
1266
+ $Total_nins += $overallmeeting{$spkover}{NUMHYPTOKENS};
1267
+ $Total_nerr += $Total_nins;
1268
+ }
1269
+
1270
+ if($overallmeeting{$spkover}{NREF} != 0)
1271
+ {
1272
+ $display_nref = $overallmeeting{$spkover}{NREF};
1273
+ $display_ncorr = sprintf("%.1f%% (%d)", $overallmeeting{$spkover}{PCORR}, $overallmeeting{$spkover}{NCORR});
1274
+ $display_nsub = sprintf("%.1f%% (%d)", $overallmeeting{$spkover}{PSUB}, $overallmeeting{$spkover}{NSUB});
1275
+ $display_nins = sprintf("%.1f%% (%d)", $overallmeeting{$spkover}{PINS}, $overallmeeting{$spkover}{NINS});
1276
+ $display_ndel = sprintf("%.1f%% (%d)", $overallmeeting{$spkover}{PDEL}, $overallmeeting{$spkover}{NDEL});
1277
+ $display_nspkerr = sprintf("%.1f%% (%d)", $overallmeeting{$spkover}{PSPKRERR}, $overallmeeting{$spkover}{NSPKRERR});
1278
+ $display_nerr = sprintf("%.1f%% (%d)", $overallmeeting{$spkover}{PERR}, $overallmeeting{$spkover}{NERR});
1279
+ $Total_nref += $overallmeeting{$spkover}{NREF};
1280
+ $Total_ncorr += $overallmeeting{$spkover}{NCORR};
1281
+ $Total_nsub += $overallmeeting{$spkover}{NSUB};
1282
+ $Total_nins += $overallmeeting{$spkover}{NINS};
1283
+ $Total_ndel += $overallmeeting{$spkover}{NDEL};
1284
+ $Total_nspkerr += $overallmeeting{$spkover}{NSPKRERR};
1285
+ $Total_nerr += $overallmeeting{$spkover}{NERR};
1286
+ }
1287
+
1288
+ print FILEINDEX "<tr>\n";
1289
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>$spkover<b></td>\n";
1290
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_regs</td>\n";
1291
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_tottime</td>\n";
1292
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_regsalign</td>\n";
1293
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_tottimealign</td>\n";
1294
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nref</td>\n";
1295
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_ncorr</td>\n";
1296
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nsub</td>\n";
1297
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nins</td>\n";
1298
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_ndel</td>\n";
1299
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nspkerr</td>\n";
1300
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nerr</td>\n";
1301
+ print FILEINDEX "</tr>\n";
1302
+
1303
+ # data for Cumuloverlap table
1304
+ $cumuloverallmeeting{$spkover}{NLISTSG} = $Total_regs;
1305
+ $cumuloverallmeeting{$spkover}{TOTTIME} = $Total_tottime;
1306
+ $cumuloverallmeeting{$spkover}{NLISTSGALIGNED} = $Total_regsalign;
1307
+ $cumuloverallmeeting{$spkover}{TOTTIMEALIGNED} = $Total_tottimealign;
1308
+ $cumuloverallmeeting{$spkover}{NREF} = $Total_nref;
1309
+ $cumuloverallmeeting{$spkover}{NCORR} = $Total_ncorr;
1310
+ $cumuloverallmeeting{$spkover}{NSUB} = $Total_nsub;
1311
+ $cumuloverallmeeting{$spkover}{NINS} = $Total_nins;
1312
+ $cumuloverallmeeting{$spkover}{NDEL} = $Total_ndel;
1313
+ $cumuloverallmeeting{$spkover}{NSPKRERR} = $Total_nspkerr;
1314
+ $cumuloverallmeeting{$spkover}{NERR} = $Total_nerr;
1315
+ }
1316
+
1317
+ my $display_Total_regs = $Total_regs;
1318
+ my $display_Total_tottime = sprintf("%.3f", $Total_tottime);
1319
+ my $display_Total_regsalign = $Total_regsalign;
1320
+ my $display_Total_tottimealign = sprintf("%.3f", $Total_tottimealign);
1321
+ my $display_Total_nref = $Total_nref;
1322
+ my $display_Total_ncorr = sprintf("%.1f%% (%d)", 100*$Total_ncorr/$Total_nref, $Total_ncorr);
1323
+ my $display_Total_nsub = sprintf("%.1f%% (%d)", 100*$Total_nsub/$Total_nref, $Total_nsub);
1324
+ my $display_Total_nins = sprintf("%.1f%% (%d)", 100*$Total_nins/$Total_nref, $Total_nins);
1325
+ my $display_Total_ndel = sprintf("%.1f%% (%d)", 100*$Total_ndel/$Total_nref, $Total_ndel);
1326
+ my $display_Total_nspkerr = sprintf("%.1f%% (%d)", 100*$Total_nspkerr/$Total_nref, $Total_nspkerr);
1327
+ my $display_Total_nerr = sprintf("%.1f%% (%d)", 100*$Total_nerr/$Total_nref, $Total_nerr);
1328
+
1329
+ print FILEINDEX "<tr>\n";
1330
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Ensemble</b></td>\n";
1331
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_regs</td>\n";
1332
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_tottime</td>\n";
1333
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_regsalign</td>\n";
1334
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_tottimealign</td>\n";
1335
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_nref</td>\n";
1336
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_ncorr</td>\n";
1337
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_nsub</td>\n";
1338
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_nins</td>\n";
1339
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_ndel</td>\n";
1340
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_nspkerr</td>\n";
1341
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_Total_nerr</td>\n";
1342
+ print FILEINDEX "</tr>\n";
1343
+
1344
+ print FILEINDEX "</tbody>\n";
1345
+ print FILEINDEX "</table>\n";
1346
+
1347
+ print FILEINDEX "<br>\n";
1348
+
1349
+ print FILEINDEX "<table style=\"text-align: left;\" border=\"1\" cellpadding=\"1\" cellspacing=\"0\">\n";
1350
+ print FILEINDEX "<tbody>\n";
1351
+ print FILEINDEX "<tr>\n";
1352
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Ref Speaker<br>Cumulative<br>Overlap</b></td>\n";
1353
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Regions</b></td>\n";
1354
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Total<br>Time</b></td>\n";
1355
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Regions<br>Aligned</b></td>\n";
1356
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Total Time<br>Aligned</b></td>\n";
1357
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>\#Ref Aligned<br>Words</b></td>\n";
1358
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Corr</b></td>\n";
1359
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Sub</b></td>\n";
1360
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Ins</b></td>\n";
1361
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Del</b></td>\n";
1362
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>SpErr</b></td>\n";
1363
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>Err</b></td>\n";
1364
+ print FILEINDEX "</tr>\n";
1365
+
1366
+ foreach my $cumulspkover (sort {$a <=> $b} keys %cumuloverallmeeting)
1367
+ {
1368
+ my $display_regs = $cumuloverallmeeting{$cumulspkover}{NLISTSG};
1369
+ my $display_tottime = sprintf("%.3f", $cumuloverallmeeting{$cumulspkover}{TOTTIME});
1370
+ my $display_regsalign = $cumuloverallmeeting{$cumulspkover}{NLISTSGALIGNED};
1371
+ my $display_tottimealign = sprintf("%.3f", $cumuloverallmeeting{$cumulspkover}{TOTTIMEALIGNED});
1372
+ my $display_nref = "-";
1373
+ my $display_ncorr = "-";
1374
+ my $display_nsub = "-";
1375
+ my $display_nins = "-";
1376
+ my $display_ndel = "-";
1377
+ my $display_nspkerr = "-";
1378
+ my $display_nerr = "-";
1379
+
1380
+ if($cumulspkover == 0)
1381
+ {
1382
+ $display_nins = sprintf("(%d)", $CumulOverlap{$cumulspkover}{NINS});
1383
+ }
1384
+
1385
+ if($cumuloverallmeeting{$cumulspkover}{NREF} != 0)
1386
+ {
1387
+ $display_nref = $cumuloverallmeeting{$cumulspkover}{NREF};
1388
+ $display_ncorr = sprintf("%.1f%% (%d)", $cumuloverallmeeting{$cumulspkover}{NCORR} *100/$cumuloverallmeeting{$cumulspkover}{NREF}, $cumuloverallmeeting{$cumulspkover}{NCORR});
1389
+ $display_nsub = sprintf("%.1f%% (%d)", $cumuloverallmeeting{$cumulspkover}{NSUB} *100/$cumuloverallmeeting{$cumulspkover}{NREF}, $cumuloverallmeeting{$cumulspkover}{NSUB});
1390
+ $display_nins = sprintf("%.1f%% (%d)", $cumuloverallmeeting{$cumulspkover}{NINS} *100/$cumuloverallmeeting{$cumulspkover}{NREF}, $cumuloverallmeeting{$cumulspkover}{NINS});
1391
+ $display_ndel = sprintf("%.1f%% (%d)", $cumuloverallmeeting{$cumulspkover}{NDEL} *100/$cumuloverallmeeting{$cumulspkover}{NREF}, $cumuloverallmeeting{$cumulspkover}{NDEL});
1392
+ $display_nspkerr = sprintf("%.1f%% (%d)", $cumuloverallmeeting{$cumulspkover}{NSPKRERR}*100/$cumuloverallmeeting{$cumulspkover}{NREF}, $cumuloverallmeeting{$cumulspkover}{NSPKRERR});
1393
+ $display_nerr = sprintf("%.1f%% (%d)", $cumuloverallmeeting{$cumulspkover}{NERR} *100/$cumuloverallmeeting{$cumulspkover}{NREF}, $cumuloverallmeeting{$cumulspkover}{NERR});
1394
+ }
1395
+
1396
+ print FILEINDEX "<tr>\n";
1397
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\"><b>$cumulspkover<b></td>\n";
1398
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_regs</td>\n";
1399
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_tottime</td>\n";
1400
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_regsalign</td>\n";
1401
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_tottimealign</td>\n";
1402
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nref</td>\n";
1403
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_ncorr</td>\n";
1404
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nsub</td>\n";
1405
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nins</td>\n";
1406
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_ndel</td>\n";
1407
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nspkerr</td>\n";
1408
+ print FILEINDEX "<td style=\"vertical-align: center; text-align: center;\">$display_nerr</td>\n";
1409
+ print FILEINDEX "</tr>\n";
1410
+ }
1411
+
1412
+
1413
+ print FILEINDEX "</tbody>\n";
1414
+ print FILEINDEX "</table>\n";
1415
+
1416
+
1417
+ print FILEINDEX "<center>\n";
1418
+ print FILEINDEX "</body>\n";
1419
+ print FILEINDEX "</html>\n";
1420
+
1421
+ close FILEINDEX;
1422
+ }
1423
+ }
1424
+
1425
+ if (! $Installed)
1426
+ {
1427
+ system ('cp', '-r', 'js', $Outputdir);
1428
+ system ('cp', '-r', 'images', $Outputdir);
1429
+ }
1430
+ else
1431
+ {
1432
+ extractJavaImages($Outputdir);
1433
+ }
1434
+
1435
+ 1;
1436
+
SCTK/src/align2html/align2html.pl ADDED
The diff for this file is too large to render. See raw diff
 
SCTK/src/align2html/buildInstallVersion.pl ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/perl
2
+
3
+ # ALIGN2HTML
4
+ # Author: Jerome Ajot
5
+ #
6
+ # This software was developed at the National Institute of Standards and Technology by
7
+ # employees of the Federal Government in the course of their official duties. Pursuant
8
+ # to title 17 Section 105 of the United States Code this software is not subject to
9
+ # copyright protection and is in the public domain. ALIGN2HTML is an experimental system.
10
+ # NIST assumes no responsibility whatsoever for its use by other parties, and makes no
11
+ # guarantees, expressed or implied, about its quality, reliability, or any other
12
+ # characteristic. We would appreciate acknowledgement if the software is used.
13
+ #
14
+ # THIS SOFTWARE IS PROVIDED "AS IS." With regard to this software, NIST MAKES NO EXPRESS
15
+ # OR IMPLIED WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING MERCHANTABILITY,
16
+ # OR FITNESS FOR A PARTICULAR PURPOSE.
17
+
18
+ use strict;
19
+
20
+ my $exe = "align2html-main.pl";
21
+
22
+ my @modules = ();
23
+ my @file = ();
24
+
25
+ open EXE,"<$exe" || die "Failed to open executable $exe";
26
+ while (<EXE>){
27
+ if ($_ =~ /my \$Installed = 0;/){
28
+ push @file, "my \$Installed = 1;\n";
29
+ } elsif ($_ =~ /\#\#\# Begin Local Modules/){
30
+ do {
31
+ if ($_ =~ /use\s+(\S+)\s*;/){
32
+ push @modules, $1;
33
+ }
34
+ $_ = <EXE>;
35
+ } while ($_ !~ /\#\#\# End Local Modules/);
36
+ my $modExp = "use\\s+(".join("|",@modules).")";
37
+ #print "Modes = ".join(" ",@modules)." $modExp\n";
38
+ ### Insert the modules
39
+ foreach my $mod(@modules){
40
+ open (MOD, "<$mod.pm") || die "Failed to open $mod.pm";
41
+ while (<MOD>){
42
+ push(@file, $_) if ($_ !~ /$modExp/);
43
+ }
44
+ close MOD;
45
+ }
46
+ ### Reset the package
47
+ push @file, "package main;\n"
48
+ } elsif ($_ =~ /die "HERE DOCUMENT NOT BUILT"/){
49
+ push @file, 'my $here = "";'."\n";
50
+ push @file, "\$here = << 'EOTAR';\n";
51
+ open TARPACK, "packImageTarFile" || die "Failed to open the packed Image tar file";
52
+ while (<TARPACK>){
53
+ push @file, $_;
54
+ }
55
+ close TARPACK;
56
+ push @file, pack("u", $_);
57
+ push @file, "EOTAR\n";
58
+
59
+ push @file, 'open UNTAR, "| (cd $outDir ; tar zxf -)" || die "Failed to UUDECODE/TAR"'.";\n";
60
+ push @file, 'binmode(UNTAR);'."\n";
61
+ push @file, 'print UNTAR unpack("u",$here);'."\n";
62
+ push @file, 'close UNTAR'."\n";
63
+ } else {
64
+ push @file, $_;
65
+ }
66
+ }
67
+ print @file;
68
+
69
+ # cat align2html.pl | perl -ne 'if ($$_ =~ /die "HERE DOCUMENT NOT BUILT"/) { system "cat DATA.tgz.uu" } else { print }' > align2html-combined.pl
SCTK/src/align2html/buildPack.pl ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env perl
2
+
3
+ # ALIGN2HTML
4
+ # Author: Jerome Ajot
5
+ #
6
+ # This software was developed at the National Institute of Standards and Technology by
7
+ # employees of the Federal Government in the course of their official duties. Pursuant
8
+ # to title 17 Section 105 of the United States Code this software is not subject to
9
+ # copyright protection and is in the public domain. ALIGN2HTML is an experimental system.
10
+ # NIST assumes no responsibility whatsoever for its use by other parties, and makes no
11
+ # guarantees, expressed or implied, about its quality, reliability, or any other
12
+ # characteristic. We would appreciate acknowledgement if the software is used.
13
+ #
14
+ # THIS SOFTWARE IS PROVIDED "AS IS." With regard to this software, NIST MAKES NO EXPRESS
15
+ # OR IMPLIED WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING MERCHANTABILITY,
16
+ # OR FITNESS FOR A PARTICULAR PURPOSE.
17
+
18
+ use strict;
19
+ use warnings;
20
+
21
+ my $str = "";
22
+
23
+ open TAR, "tar zcf - --exclude CVS --exclude .DS_Store ./js/wz_jsgraphics.js ./images/*gif |" || die "TAR/UUENCODE Fialed";
24
+ binmode TAR;
25
+ read(TAR, $_, 90000000);
26
+ $str .= pack("u", $_) . "\n";
27
+ close TAR;
28
+
29
+ print "$str";
SCTK/src/align2html/makefile ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ SHELL = /bin/sh
2
+ PREFIX=/home/userube/mozilla/zz__temp_5_rover/SCTK
3
+ bindir = $(PREFIX)/bin
4
+
5
+ all: align2html.pl
6
+
7
+ align2html.pl: align2html-main.pl buildInstallVersion.pl
8
+ perl buildInstallVersion.pl > align2html.pl
9
+ chmod +x align2html.pl
10
+
11
+ check: all
12
+ @echo "No Tests for align2html.pl"
13
+
14
+ install: all
15
+ perl buildInstallVersion.pl > $(DESTDIR)$(bindir)/align2html.pl
16
+ chmod +x $(DESTDIR)$(bindir)/align2html.pl
17
+
18
+ buildPackFile:
19
+ buildPack.pl > packImageTarFile
20
+
21
+ clean:
22
+ $(RM) align2html.pl
23
+
24
+ distclean: clean
25
+ $(RM) -r *~ makefile
SCTK/src/align2html/makefile.in ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ SHELL = /bin/sh
2
+ PREFIX=
3
+ bindir = $(PREFIX)/bin
4
+
5
+ all: align2html.pl
6
+
7
+ align2html.pl: align2html-main.pl buildInstallVersion.pl
8
+ perl buildInstallVersion.pl > align2html.pl
9
+ chmod +x align2html.pl
10
+
11
+ check: all
12
+ @echo "No Tests for align2html.pl"
13
+
14
+ install: all
15
+ perl buildInstallVersion.pl > $(DESTDIR)$(bindir)/align2html.pl
16
+ chmod +x $(DESTDIR)$(bindir)/align2html.pl
17
+
18
+ buildPackFile:
19
+ buildPack.pl > packImageTarFile
20
+
21
+ clean:
22
+ $(RM) align2html.pl
23
+
24
+ distclean: clean
25
+ $(RM) -r *~ makefile
SCTK/src/align2html/packImageTarFile ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ M'XL(`-QX"$H``^P\2VSD1G9*$`21$!D.L,@:>RI-9J;9ZH^Z6Z.QK1Y)UDCS
2
+ MD5<>:4<RG(EWTF:3U4W.L,E>DJUN3G:`1>($"`(DU\#'/03(<6][VTO@`+DX
3
+ MR,'W('O.+0CVDLU[KXID\=.2QI8=>Q$"HLCZO'^]]ZJZBLVU9\':]$7O63#T
4
+ M];%E&T'S6;!PM5<+KC??W%AHM5NW;[77X;W37M_8H/)6Z];&[=NW%MJMC3<W
5
+ M-J!THP7M-M;7UQ=8ZXKI*+TF0:C[C"WHS[SPO';!F'/#FE\OF&DE_[\EU]HJ
6
+ M.[7L@+E>:!N<C4`<K,_9Q`V]B6%QD^DATQV'A?:(!\WEI>6EO+$PN,Z:K--<
7
+ MO[V\=&IQYN@A!RAGW`]LSV4`7#_3;4?O.QR@+2]983C>7%N;3J?-J>Z$W'_A
8
+ M^6[3\$;+2Y[/E%J3G]F^7E:C]#,Y$K7GC2/?'EHATXPJZX"%->!VBWU`#=F?
9
+ M8$NV"WQ0HX#Y/.#^&3>!HSV?`\$F6V^R=KM)?5D_4GLR[0/>WYR#'ZACU>6E
10
+ M0QU8'GFF/;"YN<DZ`.DV`;N-Y!US?^#Y(]T%$7MCD*7]0@]!.`&#8G;@`C"7
11
+ MA^S>;.QX/O>7EX"`4\L;Z0&[[^ON<Z:[)GO7LUSVT'/,8.KYH06D#VS'.?:<
12
+ M:`AB'O'0\DQFC\8.'W$7.0(@[^EA:-E\PAZ"$KE/"GP((F`J1>^"?DX,WQZ'
13
+ M[('4*SNT^[[N1]#AV/?.;),'$D.PO-1@H<=,7Y\RQW9Y4`=I&J'N#AU\YHYC
14
+ MCP-\&@O*H,/BU`XM!B/(`/&0'6!'!I09SP%`4)<PD1\%&'$=PU/1AGP6`F6/
15
+ MCD[O;;*C,?>%,.ML,'$-(5?L"ARXAF6[0V;I9YQ!*PLTVN?<C97`S>4E`,H'
16
+ M`]NPN6M$U`^'N@G4Z2YB#"R0-E+)O`$+O(D/$C,\DY,L#P_V[CTZ`2H.'QP?
17
+ M8@$-)D<(#TU_X',.O0;A5/=YET7>A!D`U^>F'82^W9^$G-DAHEWS0.]D01&6
18
+ M3%P3B`6*@5M_1,CQY<&C]]DA$`-U#[@+G#OL>-)W;`-H@0'L!IQI2$N5@>V,
19
+ ML2:PA"E@[_M(S8FDAMWW``F)KLNXC<)97HI';:?9CE%*N'4&IJJ!.P`>?!*@
20
+ MYP(6-Z(![\?CO5DFA919L%"7H%K>&"T`X`&S4U0\NIV`#R8.F`,T91\<G#X\
21
+ M>O^4[3YZPC[8??QX]]'IDRY#4_*@EI]Q`0@M'L8<`Y9`WV$$9"\OO7?O\=Y#
22
+ MZ+![]^#PX/0)DG[_X/31O9,3=O_H,=MEQ[N/3P_VWC_<?<R.WW]\?'1RK\G8
23
+ M">>QD$&<95*.A4'C=@1CE9D\!.<F7.,3T"Z8R\0QI<5Q@]MGZ$3!8L;1*^A0
24
+ M=SPP6QHVH2+++K,'Z*KK;.K;8#E@G@6U+B^E>JV#;S&:=;;Q-COEZ!G8L:,;
25
+ MH,J3"79?7V_5V5TO"+'E>[N,06!NMQOM]=:;C+U_LELGOQL`<,7W#=U)T_.'
26
+ M:\B1PP?AFD.L-*UPY"POK:ZA(,".(*@^&_9L**W3`Z=_`W"3]&!ZHGSDO0`L
27
+ M\.#>8EM,,SUC@MZKZ>@1V!.[>9.%T9B#X)(:P]$!7\!6MM@U'"0#<"7FM6I7
28
+ MX(T]`#.LY_L/3]_39G5F@W_^,_!",\"0@.E[9L1^_&/F3AP'^BX2C=!@IN"<
29
+ M-6U0AA_NFL]`:FX(\`YS>&578`?)I\XK`M3-FU"UF$#2QV/NFGN6#<:1!9%M
30
+ MF?))<>DQN$)^;@?-5ME2>FG5:C/@X0GD-^%=/D!C/0^.+?ON>2[ZUXGN0.@9
31
+ M(M`242]*W0+JA%UZ0D'`8UZ*8.7SA8=&`8`2.`DSF'@@W*GMFMZTZ:&GEWW`
32
+ M;D07B3#!%81@E<WWO!='8]VPP1T44+[,6<K8#?<]0Y-&@L.M.77-9D(%#35-
33
+ MTKE#XQ&-_?$8^K#-Y)W$$K\`;95*.:X]]VS?&\7H<)R@71;19C2)L&<Y;6K4
34
+ MQW#/1"W:[EP57I)\>Y`"9?&3:KK:[!78/.`QE^5PBX-+NR98N^>:UQ)_<24B
35
+ M/X`6%U$3&VEM*\%P>009^SFG]>CYOGV&7BD")UYG5KX;(*_<,>TS1H:\=6WL
36
+ M!39VW-3[@>=`!.U6:CAJ*^A[-RNL!N938Y7Q+"X/O3$51]GBJ6V&%E5,LQ46
37
+ MQY28:JQLC0&9UR:F8UJK7JE-:U`%_RWZWZK&K?JZ\7SH8\AI&!ZDKP1)2!5?
38
+ M&;725L28W6&5K@>9PL#QIIN6;9K<K8!"*Y6J`-:]MGWGAVO`_O9<V8%5G2^]
39
+ M&S<JM11_K0*$SN@>T7U*=POO\U`<^^%5:*CO^9##-1)%2<%#.NC8)LN+B56^
40
+ ME&9;WU*-'D;^1;*F7(`IPMFZEDCG&DN%(XJC3#$)1U1,,Q5"2*+&RM3TA\2F
41
+ MJ,IJB'@A<K9_Z"K\H!?W^9"C$V9K-VYH'_YI]VFMVKWH_]JPJP@C]G!"!CX/
42
+ M)[Z;>**FS\>8NVE((^&J$[6J)>;TT"U:9E&U@N?K[2Y9W?5.%ZWL^GI76-7U
43
+ M6UUI3=<W@'G2(W!>+5$ET`CCYIO,0%<=D-=O)2/Q>OL"UL!*;5>;M<%,X6_6
44
+ M@?^=))9`UM=FVU`*)8M81#&]-^M@0.YTDX(("R)1("K;]"S*Q3-`VL*NHH)>
45
+ M1(^7,E4P*<QW&D@+Y*];.,&WFB`=+>HTHG:U'F<"2"O!Q9((9@$^YJ<14@JT
46
+ M[[!&&P9IFY)FX@$`;T,:&668&&,G,[ISAZ`LCOT)O$-A`]M#:5444V'#%/KT
47
+ M"#TQ,(6,`::CT+;1J`+B%@(7T!=K-=&&D(^32EDK'(`(E9[P#K,&/K2KHM=B
48
+ MA*Z!^)(%8RP`"N6K0@8);W&1.S"ODJVHG(I+$'4`4ZT=XR);H,Y%R<Q*)1,5
49
+ M)!,)R9!""#4R#7J_@PI2A)((+%(%%LLD)ZFX6&5A5JL1#T"]%S6B6B*NHKSR
50
+ M`E/)BT46LZT@FPLGTU'<5<)HS"2$=6+*J&&,Y3)"*."_K%0\(9:HX4755Q5!
51
+ MQFS*F8O!@_%$*G,OYWB3SOYOKC]!P$$\IPE"WWO.N_/<3%S(6CB+"QKK.3]!
52
+ MK"(P+5@U9ZM$7O`CR,_:-3-:-:,UZ`T5U2KXGX86;&^WJU!:96O`FE"7Z+VB
53
+ M!8U;0"<!,+CM:+T`IQ+T3O$$"ZH0Y-M9PV0)!4$B>]V,)460@K6.6'[X9GK-
54
+ MFF[6@8.ORW/J)CI/B:_H/9'R"]0<9=6,^@4UH[9!S;&.9PVIYNAK4+/H6:KG
55
+ MJXX!-1!@]VJC02^0X4`WOVGQ(":MD]#V]48$Q(\A017-%4<%0M$1."X3&?:]
56
+ M,/Q-C`U8:?I3C`O^9'Y`^`(>]$*W28C\J5SL45=@VFE**6A;@7_GN=@+O.<<
57
+ MAYDX[I=)S#N?G"O).K-RB:Y(+GD)E,LIB527$]`KR*4X:([.-)S2U1G,_.J,
58
+ MYGUU)F9]RBJK#EQ0'<2/.NO#FVB"K]!DZIEQ@YM0;]&K)IK<;%=KU,A`>T=<
59
+ M-;W.##1Z0%GKQR.A)08"O7NRP$M*=*1`TU?U*BJ0]9$$K;_:KTI]TB*XINL4
60
+ MW[1V0^NC2C%6]:E_2/7]/M:#RG5]51--&D+QN'Z",I(:CV*=I&$W9'<R^H<"
61
+ M4$&_#X!H6-76I<Y#J@!<6+JJ@3)SSAE_A]+"2\!#V]1U`29JM.?#CSG2T$Z)
62
+ MJY@8-#_,8\2;!6\8,5+CF][L8.YHW>R4)4-'9S\P`\V8H;[JK#&KH5N>U4#=
63
+ M\(;^&8"U:Q:^*D8_MS?Z9&@OND-/T'BALV+CYX#)$V$).+0*)N"HF9@2A$HB
64
+ M),BSL27D%V5D%U!%HH%&(\H$(#5>&;,&&371H\LYL.81/"0M76R/V]=B%L[O
65
+ M5#9@8?ISB2%;,HF@IF@\08/"F.BC%/P?#/6O<F!WDQ4:2&QQN*&I4YK;J>+/
66
+ ME\1%8Z,=SZ`$%[*@FHFJ18]$+D/$C)E39^.9C[<0;WV\3=4($I4$#\6CQ,-N
67
+ MKD^9ZU34\9)S*^<`+7<LK^99<JY%]2W+22HY;;1SB20(!NVGUJYIP<UTB<5*
68
+ M)@_9-!&!6'.`!&EG(#L+,)-J4FL5P[F>I0'M:U/%OX!W\:2C@JK4Q61\3";3
69
+ M3962<:KS',U<3R,`Y6>,&6<3%/U,SM'HR$HC0.;F]RG/F7HT.,4PT6#8M,D$
70
+ MJM(5+/;ZZ=@OK9>#IH>BZ8E1TQ,#OJ>O]N20[XDQW^NO]I)1#S/24#1+!WXO
71
+ M&?F]OH0E!G\O&?T]$FY/">QR?$(SET_9KN_KD28SO5E84MJ#T9LM[DH0'[:>
72
+ M(C?R-12O_6[<2;SW^L*1?O7CGDB"OZ;#W6%H/54L$:F#/Z6F8)9?MZ_X4L1^
73
+ M^3&4R+X7E:X%]%2=)%ZF)Z31(W'T<HHAXZL)ZXM%T)NEM6@2>%,8ZT72.(HN
74
+ MKA=>G@!42"]FLZ>H9`Y)R;C`QGG%O`*A.=J$)N2(B_)0I39ZJ3IZT5R<C?;3
75
+ M1J.XYO$R72XJ";\]>I9#CTIPE*=&EL1H`HQ;SC2$9-,@AG]WF`/_:K7<Z)1[
76
+ M80BN_32_>Z=@.++9'8;D0$J!YDSO7I13YDQ0![6Q&"Z;W_;BZ"-^QH$@VU/6
77
+ MX3-!2$0A040B[5102:&ZLI0?8@5"LZ%GI@22DB0WWSZ?YY9W*492E8>+HV`9
78
+ MU%<E8\[TF):4OJ(I<IPVOW+.W,DDS;J.^_^@]/P4NG/I'+J3FQUGEYZ^:7-D
79
+ M8/\R\^-.66@Z9S[8F3,A)'29R6!A\24_I&'HQK/>DCEO=I&HU`P?X[:3PDZ/
80
+ M.=.\P@H0=`GR,U`@B.J".)_-]:J!C4]K05E/K`U$ST90/DE%>L5:;.GN%-R(
81
+ M?@@>558+6E(\:;4D4ORO665-)*T7-($&276>W&?!\+[GAIE-:,>'NP>/0+25
82
+ M`=0TIF(7A(N;_AW:^B1:W3TZW,\WZGN.J30Y.-T]/-A+&M%>C4T[U!W;*+3J
83
+ M27AJ1[F+!FLR:'L)X#P`P2':!G(ED]F$QVZ1^1.RG`S[^T>GI_>0%$H$)#C1
84
+ M+@48]RN"C$]":#8NRKBF"CK@X1YM"1)P[LM>6D7WAY4ZJRB;AF"L^<-FZ!UZ
85
+ M4^[OZ0'BJLA9?0PK(2I&K\T2GZ2,BR2\X%!=`<-J5Q6_DK$7:)K\EM!-JW%4
86
+ M4Y4("=UL1S1XJHTMO\2=S1KMW'2@%&]GOQQKIKR`<ZXW*T-1CN!2X%]*;2<*
87
+ M./9M-Z1S*8H.0&]9+8R55E"9J$)N4\W+A#P-(:=-BPIE8I^7@+*3[IMBFW('
88
+ M6$[N&6BT4WY'[)N##@0AWK,([_38+>-1#J2$O8$^`O_WHHY;K[)\#L+[.FY?
89
+ MA19=I?`$-UP'+S)%(<9S`(!I(R(0/J>('W6!!Y4<H<!,F51J:OO"IR<TI6GO
90
+ M5HM!NGMGEJ3<C+)?5BU:B3:#S`L`T1V>:VWQ!O^K1?+PW)$TE1P9TNLKTBGL
91
+ MWYW/+1[+RD',PE+%(JJ[F3K)2<HP,9%YG>',`0I;97PAC'OB_)0J]:,SW;D<
92
+ MJT<7<(J"RR'`HCP"-?54L<0YIS;%I*1=3=).S4H+L*'(/+6I6)U-5FR3Q=KS
93
+ M,L]"ZEGRT\RKIJ,7YZ,7)Z1BS=4$@9A6XDNFX-39-W;!-9>ERE4IG%#)`A.S
94
+ M0-D#=';!.DMI-@M`LC_QJ,..1":G/T)R)1,VV:@FD]1LNR^XWEE,I$LSZ4M,
95
+ M\Z9E/ZO$HVIME17/=-8O/M1)Y^V>Z6=Z((YQ)GD,'KYUF6[JXY`.A,5'T(;F
96
+ MP4@?\ON`C)LQ.O2TZK%7Q^[C^=CXT"-T?;#/VLVWFK>@Z<2EL\'*P;"^-PFY
97
+ MX^")V+6A2>?`3A_N/OK^"1Y3^[[M!R%WV8EA39P7A`KI&,>H[1D/5L3103!*
98
+ M/!`;<,'"P'9-/,,9<L-R[1]-N.`!.,-3F'##XW9].@?H>V=XHA-$Y(.X1GWN
99
+ M4T?$X_,SVYL$`G0*O2X.BD9L$L1-`\<;<Y(IL">@6]P9(Q.Z^0S/1ZOD!5@.
100
+ MB,T)2$AGKFV`_5`#V_-[?!8")7J3X;&XU&66!`<\O!CUP-F*A^Q^"+L;/T7)
101
+ MT\AVP9I&^BPM$IM&TE?:.Y*\@ABA'NYJ41ATTQ4JEU(2HD.&&%E)":=;96)'
102
+ M=QP!%I&$I`N&(`*,)!5+*8KCPE5;+%RY90M7<1]:?4+H<OTIAXC65,HZ;9,\
103
+ MXDY9.N1"S,N$&*Q$P%V(#'>VA"1A>J721'LN0%<'(*>2%?5%6Y2+!?64Q5:!
104
+ M176];<7.K:JA8A!ZLF"))9T4[OP%3-G3+O2TLSUI=T\B".@4+XO1?B"EHA-7
105
+ MT.:T-C`1=?)K@"FL60:6V&BDU'2>%NEG$O!V$7">EA1PGOS.7)0*,>U+$&-`
106
+ MRFJ[M"(D2MG:6G*(7WP-@,[P9[XCD`H((S3MWJ/?9",A+<G58FPW'Z*1U&JX
107
+ M)JUL)82PA_U6(5CB!BO<R"AW5>'!EOAG7U5H:*_"2F-TVRKJK2O%G<@IAM0,
108
+ M/#_4T*\-N=\##S_6?5XMMWOR*F#Z6[&&U=B<4/:4\LKT'3+SAE*;;L`OF;)A
109
+ M$@N39O38B@L-\9?K8I)]N2-;D'.%O!&,=8-ONMX4)O_R--3<XUCSSF,MBE42
110
+ MF#W93D3U3)E6I<>\9+O`?L'3`U8TS5+;E!_`P@9*EU"<>=J6G4`03'97CEZI
111
+ M248J0%J5JT)D,T5N\=@VGK.[CC<:08B#*+CK.-Z4@ISX?(/XC@`2':<2>-(T
112
+ M_6@#Q5,,E8X]I//YRTO4H.^%%N3MOOT"F(:T)6(:;PZ;XGL<5>IU!H'9-J@.
113
+ M#[[3=P)T%70:1+/TEQI!NLI-I'P1F\B?1OK"!B'/7M;DYI5,%Q!.@RB$>D%J
114
+ MK?)ML:14&91-JGJP1\,3WTA4@?M,F/Y%E/!EA8Y2F^:J2@Y()BQ7[@#I+/`-
115
+ M<?Y/\"'.!Q;/$A8/$>*3IN\PK<(J-;TJ3D)B30I_KB`-A^N^*L2BO+;8M6O)
116
+ M9/'<0\SQ?)\/Y#'F+"ZYP*]BB]?Z<?J$.X$B&$E1_YPU$+^&7:*P9J@K!&5-
117
+ M^N<T<2[=)(?H9=DJJM9.5\_EJI=6@7%LZJY>'W*7G^EU2.?/.+J:>J"[02.`
118
+ M7'U0J3/A4)H#WQOM6;J_![,+K35;AT`$]P[>WVS1_:UJ75GM2O'%*[Z5/Q+?
119
+ M@$K7QI7SX*)@ZM)/:7"G/5SX>8-NLM-K11.?0H`J^8$#\80?7*A6DR];R!/[
120
+ MR>^]-GU8HA(0&Q7LLV*;TC;&NDW+?^);!]A1W2<3FP_;RGQ[84>:6.:S!%#^
121
+ MH6T^C3^=(4+\9MIOR,-[8K)Z-SHP2T%DFVA(9`Y:_%&.1<6&<64A(12_^%"P
122
+ M^>I.V4#8E')?S`A""'8G_2`#M".I[R0?+Y`E@'I'^8@`E(H7,L'R961MH(-T
123
+ ME=]IE%\6<CF4-JM'V?.RV@P3R2J3^^8U#4]'1=75=@+O*K__U5RST74':Y0`
124
+ M]<SGS:$]N$H$"^+3:/B-M_+OO[5:&ZW;^>^_==H;___]MZ_C>G!P_ZVW]=<6
125
+ M7EOXKX6%7\Z_/O_\\\\^^^S33S_]]:__YQ=T_3Q[_2R^_I&NG_[TIY]\\LG?
126
+ MT/7QQQ^_?/ER0M>0KH\^^NC)DR<_H.LN75?"S,JO?N>W%A9^?Z&.+\C3PN\:
127
+ M[_S5^&']>W_W3^_N7_OKT[]]_9___2</_YC=^Y=?OO/Z&]_YP]?^\HVWW_CM
128
+ MG_SY?_S;KUZ_\7M_\=&__GS\SC_\]]V?_;WYG]>CO3_X[G??^-[T1F5E_SO_
129
+ MVTX=HB`01'$8]P86FZZXKLS:!8M)4/0P1N]B,HH6XP2C8<($+S#!8#`8MDR8
130
+ MJ,,#PPJV106_WPG>"]\_:26=;J^?-Z?U+%/YNCUKI$JEJ_EV-QG71I5<_Q4O
131
+ M_2^6/]+_8$C_GU#J__Y>",%[7Q1%[/\FKF67I[-PSL7).`EKK3'F*`Y":QV7
132
+ M8B\VHI)GZ!\```````````````!_Y@%8KS5]`'@`````````````````````
133
+ M````````````````````````````````````````````````````````````
134
+ M````````````````````````````````````````````````````````````
135
+ M````````````````````````````````````````````````````````````
136
+ M````````````````````````````````````````````````````````````
137
+ M````````````````````````````````````````````````````````````
138
+ M````````````````````````````````````````````````````````````
139
+ M````````````````````````````````````````````````````````````
140
+ M````````````````````````````````````````````````````````````
141
+ M````````````````````````````````````````````````````````````
142
+ M````````````````````````````````````````````````````````````
143
+ M````````````````````````````````````````````````````````````
144
+ M````````````````````````````````````````````````````````````
145
+ M````````````````````````````````````````````````````````````
146
+ M````````````````````````````````````````````````````````````
147
+ M````````````````````````````````````````````````````````````
148
+ M````````````````````````````````````````````````````````````
149
+ M````````````````````````````````````````````````````````````
150
+ M````````````````````````````````````````````````````````````
151
+ M````````````````````````````````````````````````````````````
152
+ M````````````````````````````````````````````````````````````
153
+ M````````````````````````````````````````````````````````````
154
+ M````````````````````````````````````````````````````````````
155
+ M````````````````````````````````````````````````````````````
156
+ M````````````````````````````````````````````````````````````
157
+ M````````````````````````````````````````````````````````````
158
+ M````````````````````````````````````````````````````````````
159
+ M````````````````````````````````````````````````````````````
160
+ M````````````````````````````````````````````````````````````
161
+ M````````````````````````````````````````````````````````````
162
+ M````````````````````````````````````````````````````````````
163
+ M````````````````````````````````````````````````````````````
164
+ M````````````````````````````````````````````````````````````
165
+ M````````````````````````````````````````````````````````````
166
+ M````````````````````````````````````````````````````````````
167
+ M````````````````````````````````````````````````````````````
168
+ M````````````````````````````````````````````````````````````
169
+ M````````````````````````````````````````````````````````````
170
+ M````````````````````````````````````````````````````````````
171
+ M````````````````````````````````````````````````````````````
172
+ M````````````````````````````````````````````````````````````
173
+ M````````````````````````````````````````````````````````````
174
+ M````````````````````````````````````````````````````````````
175
+ M````````````````````````````````````````````````````````````
176
+ M````````````````````````````````````````````````````````````
177
+ M````````````````````````````````````````````````````````````
178
+ M````````````````````````````````````````````````````````````
179
+ M````````````````````````````````````````````````````````````
180
+ M````````````````````````````````````````````````````````````
181
+ M````````````````````````````````````````````````````````````
182
+ M````````````````````````````````````````````````````````````
183
+ M````````````````````````````````````````````````````````````
184
+ M````````````````````````````````````````````````````````````
185
+ M````````````````````````````````````````````````````````````
186
+ M````````````````````````````````````````````````````````````
187
+ M````````````````````````````````````````````````````````````
188
+ M````````````````````````````````````````````````````````````
189
+ M````````````````````````````````````````````````````````````
190
+ M````````````````````````````````````````````````````````````
191
+ M````````````````````````````````````````````````````````````
192
+ M````````````````````````````````````````````````````````````
193
+ M````````````````````````````````````````````````````````````
194
+ M````````````````````````````````````````````````````````````
195
+ M````````````````````````````````````````````````````````````
196
+ M````````````````````````````````````````````````````````````
197
+ M````````````````````````````````````````````````````````````
198
+ M````````````````````````````````````````````````````````````
199
+ M````````````````````````````````````````````````````````````
200
+ M````````````````````````````````````````````````````````````
201
+ M````````````````````````````````````````````````````````````
202
+ M````````````````````````````````````````````````````````````
203
+ M````````````````````````````````````````````````````````````
204
+ M````````````````````````````````````````````````````````````
205
+ M````````````````````````````````````````````````````````````
206
+ M````````````````````````````````````````````````````````````
207
+ M````````````````````````````````````````````````````````````
208
+ M````````````````````````````````````````````````````````````
209
+ M````````````````````````````````````````````````````````````
210
+ M````````````````````````````````````````````````````````````
211
+ M````````````````````````````````````````````````````````````
212
+ M````````````````````````````````````````````````````````````
213
+ M````````````````````````````````````````````````````````````
214
+ M````````````````````````````````````````````````````````````
215
+ M````````````````````````````````````````````````````````````
216
+ M````````````````````````````````````````````````````````````
217
+ M````````````````````````````````````````````````````````````
218
+ M````````````````````````````````````````````````````````````
219
+ M````````````````````````````````````````````````````````````
220
+ M````````````````````````````````````````````````````````````
221
+ M````````````````````````````````````````````````````````````
222
+ M````````````````````````````````````````````````````````````
223
+ M````````````````````````````````````````````````````````````
224
+ M````````````````````````````````````````````````````````````
225
+ M````````````````````````````````````````````````````````````
226
+ M````````````````````````````````````````````````````````````
227
+ M````````````````````````````````````````````````````````````
228
+ 9````````````````````````````````````
229
+
SCTK/src/chfilt/chfilt.pl ADDED
@@ -0,0 +1,1042 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env perl
2
+
3
+ ### This changes the function of a runtime warning to dump a stack trace
4
+ #use Carp (); local $SIG{__WARN__} = \&Carp::cluck;
5
+ ### This dies on a warning after the stack dump
6
+ #use Carp (); local $SIG{__WARN__} = sub { Carp::cluck(); die; };
7
+ #use Carp (); local $SIG{__DIE__} = sub { Carp::cluck(); die; };
8
+
9
+ use strict;
10
+
11
+ # File: chfilt
12
+ # History:
13
+ # version 1.0 Released 950921
14
+ # version 1.1 Released 951006
15
+ # - For Spanish, it now converts a set of predefined words to
16
+ # interjections.
17
+ # - Corrected the order of deleting "--" from the transcripts
18
+ # - Normalized improperly formatted words in (( )) markers
19
+ # version 1.2 Released 951025
20
+ # - The "add_spaces_for_japanese_punctuation" function was splitting
21
+ # words that contained vowel elongation characters
22
+ # - Japapese quotation characters are now removed
23
+ # version 1.3 Released 960418
24
+ # - changed the exit codes to be 0 for successful completion, or
25
+ # 1 otherwise, (thanks Barb).
26
+ # - added English support
27
+ # - modified the main loop to first read in the entire file, then normalize
28
+ # it, by deleting empty lines and concatenating continued lines together.
29
+ # - added the -i option
30
+ # - added the translation flag option "-t"
31
+ # - added the option -I to not make alternations for interjection words.
32
+ # - added the equivalence class option "-q"
33
+ # - added the hyphenated word alternation flag "-a"
34
+ # version 1.4 Released 970711
35
+ # - added a the pem output format
36
+ # - added the -u option
37
+ # ????? is there an unresolved issue for Japanese ????
38
+ # version 1.5 Release 971010
39
+ # - Spanish: installed hesitation filter, removing interjections.
40
+ # - German: installed hesitation filter
41
+ # - Arabic: updated hesitation filter for *romanized script*
42
+ # - removed the -i, -u and -I flags
43
+ # - removed all code that made altenations with NULL
44
+ # - added the '-d' optionally deletable flag
45
+ # version 1.6 Released
46
+ # - For Arabic scoring, translated the arabic script for an apostrophy to a hyphen
47
+ # version 1.7 Released April 7, 1998
48
+ # - fixed a problem with Out-of-Language markers within an unintelligible markers
49
+ # - fixed a problem with unintelligible markers within an OOL markers
50
+ # - added a filter to remove empty optionally deletable flags.
51
+ # Version 1.10
52
+ # JGF updated to new version or perl
53
+ # Version 1.11
54
+ # JGF added support for Miss. State transcript
55
+ # JGF modified the PEM output to pass through the duration times as strings
56
+ # Version 1.12
57
+ # JGF commented out part of the MState code that converted 'OH' and 'AW' to hesitations
58
+ # JGF Correctly handle possessive ancronyms in MState transcripts
59
+ # Version 1.13
60
+ # JGF Added processing for spoken letters. Previously they did not exist.
61
+ # JGF Added code to remove '^' for proper names
62
+ # JGF Corrected the line header extraction code to handle empty transcripts
63
+ # JGF Added -i and -k options
64
+ # JGF Added code to remove 'aside' sgml tags
65
+ # JGF Added -p to pad segment times with silence and -s to smooth segmentations
66
+ # JGF Added -E to exclude overlapping speech
67
+ # Version 1.14
68
+ # JGF Added -c to read contractions
69
+ # JGF disabled all old arabic character-specific processing
70
+ # JGF Uses Getopt::Long now tp process the command line arguments
71
+ # JGF Modified the output for stdout to be "-- -". The new Getopt
72
+ # is interpreting '-' as an ambiguous arguement.
73
+ # Version 1.15
74
+ # JGF added Arabic processing steps for 2004 arabic transcripts. See the Eval
75
+ # plan appendix for Arabic.
76
+ # JGF add use strict pragma
77
+ # Version 1.16
78
+ # JGF added code to check for unannotated, non-posessive contractions IFF contractions
79
+ # are to be processed.
80
+ # Version 1.17
81
+ # JGF Added -C
82
+ # Version 1.18
83
+ # JGF Added two new hesitations
84
+
85
+ my $Version="1.18";
86
+
87
+ my $usage = "Usage: chfilt <OPTIONS> infile outfile|-- -\n".
88
+ "Version: $Version\n".
89
+ "\n".
90
+ "Desc: chfilt converts a Callhome transcription file, 'infile', to STM\n".
91
+ " format, written to 'outfile'. If '-- -' is used as output, the output goes to stdout.\n".
92
+ "\n".
93
+ " OPTIONS :==\n".
94
+ " -l <language> Identifies the language on the transcript\n".
95
+ " Current chfilt can handle: mandarin\n".
96
+ " spanish\n".
97
+ " japanese\n".
98
+ " english\n".
99
+ " arabic\n".
100
+ " german\n".
101
+ " -m Read Miss. State Transcripts\n".
102
+ " -b b_time Output segments After 'b_time'.\n".
103
+ " -e e_time Output segments ending before 'e_time'.\n".
104
+ " -d Output text with optionally deletable tags.\n".
105
+ " -q Word1=Word2\n".
106
+ " Add alternations to the output such that Word1 and Word2\n".
107
+ " are equivalent\n".
108
+ " -t Word1=Word2\n".
109
+ " Translate Word1 to Word2\n".
110
+ " -a Convert all hyphenated word to alternations whereby the \n".
111
+ " two alternations are the word with hyphens deleted, or\n".
112
+ " the word(s) with hyphens converted to spaces\n".
113
+ " -i Add inter-segment gaps to the stm records. This option\n".
114
+ " requires -b and -e to be used\n".
115
+ " -k Keep lines with no lexemes in the transcript rather than\n".
116
+ " ignoring them\n".
117
+ " -o fmt Set the output format to: \n".
118
+ " stm -> Output STM format (default)\n".
119
+ " pem -> Output PEM format\n".
120
+ " -s time Smooth the segmentation (i.e., merge segments) that hava gap\n".
121
+ " intersegment gaps less than 'time'\n".
122
+ " -p time Pad segment boundaries with 'time' seconds of silence if\n".
123
+ " the time is available\n".
124
+ " -c Don't expand the contractions if they are annotated\n".
125
+ " -C (numbers|letters)\n".
126
+ " If 'numbers', change channels A and B to 1 and 2 respectively \n".
127
+ " If 'letters', change channels 1 and 2 to A and B respectively \n".
128
+ " -E Exclude overlapping segments in the output STMs\n";;
129
+
130
+ ##########3 Globals
131
+ my $Language;
132
+ my $OptDel;
133
+ my ($NewBeginTime, $NewEndTime);
134
+ my $Format;
135
+ my $KeepEmptyLines;
136
+ my @Translate;
137
+ my @Equivs;
138
+ my $AltHyphens;
139
+ my $ReadMSstate;
140
+ my $ExcludeOverlap;
141
+ my $PadSilence;
142
+ my $SmoothSegments;
143
+ my $ExpandContractions;
144
+ my $AddInterSegGap;
145
+ my $HES;
146
+ my $InFile;
147
+ my $OutFile;
148
+ my $id;
149
+ my %TranslateAArray;
150
+ my %EquivsAArray;
151
+ my @Trans;
152
+ my $ChannelsTo = "asis";
153
+
154
+ use Getopt::Long;
155
+ $Getopt::Long::ignorecase = 0;
156
+ my $ret = GetOptions ("s:f", "p:f", "l=s", "b:f", "e:f", "o=s", "t:s", "q:s", "a", "d", "m", "i", "k", "E", "c", "C=s");
157
+ die "\n$usage\nError: Failed to parse argements" if (! $ret);
158
+ if (defined($main::opt_o)) {
159
+ $Format = $main::opt_o;
160
+ if($Format !~ /^(stm|pem)$/){
161
+ print "\n$usage\nError: Unrecognized format type --> $Format\n\n";
162
+ exit 1;
163
+ }
164
+ } else {
165
+ $Format = "stm";
166
+ }
167
+ if (!defined($main::opt_l)){
168
+ print "\n$usage\nError: Language option is required\n\n";
169
+ exit 1;
170
+ } else {
171
+ $Language = $main::opt_l;
172
+ if ($Language !~ /japanese/ &&
173
+ $Language !~ /mandarin/ &&
174
+ $Language !~ /english/ &&
175
+ $Language !~ /spanish/ &&
176
+ $Language !~ /arabic/ &&
177
+ $Language !~ /german/) {
178
+ print "\n$usage\nError: Language not recognized\n\n";
179
+ exit 1;
180
+ }
181
+ }
182
+
183
+ if (defined($main::opt_b)) { $NewBeginTime = $main::opt_b; } else { $NewBeginTime = 0.0}
184
+ if (defined($main::opt_e)) { $NewEndTime = $main::opt_e; } else { $NewEndTime = 999999; }
185
+ if (defined($main::opt_k)) { $KeepEmptyLines= $main::opt_k; } else { $KeepEmptyLines = 0; }
186
+ if (defined($main::opt_t)) { @Translate = split(/:/,$main::opt_t); } else { @Translate = (); }
187
+ if (defined($main::opt_q)) { @Equivs = split(/:/,$main::opt_q); } else { @Equivs = (); }
188
+ if (defined($main::opt_a)) { $AltHyphens = 1; $main::opt_a = 1; } else{ $AltHyphens = 0;$main::opt_a=0;}
189
+ if (defined($main::opt_m)) { $ReadMSstate = 1; $main::opt_m = 1; } else{ $ReadMSstate = 0;$main::opt_m=0;}
190
+ if (defined($main::opt_E)) { $ExcludeOverlap = $main::opt_E } else{ $ExcludeOverlap = 0}
191
+ if (defined($main::opt_p)) { $PadSilence = $main::opt_p } else{ $PadSilence = -1.0}
192
+ if (defined($main::opt_s)) { $SmoothSegments = $main::opt_s } else{ $SmoothSegments = -1.0}
193
+ if (defined($main::opt_c)) { $ExpandContractions = !(defined($main::opt_c))} else{ $ExpandContractions = 1}
194
+ if (defined($main::opt_C)) {
195
+ die "Error: Unknown channel conversion '$main::opt_C'" if ($main::opt_C !~ /^(numbers|letters)/);
196
+ $ChannelsTo = $main::opt_C;
197
+ }
198
+ $AddInterSegGap = defined($main::opt_i);
199
+ die "$usage\nError: -i requires -b and -e to be used"
200
+ if (defined($main::opt_i) && (! defined($main::opt_b) || !defined($main::opt_e)));
201
+
202
+ if (defined($main::opt_d)) {
203
+ $OptDel = 1; $main::opt_d = 1;
204
+ $HES = " (%HESITATION) ";
205
+ } else {
206
+ $OptDel = 0; $main::opt_d = 0;
207
+ $HES = "%HESITATION";
208
+ }
209
+
210
+ #### The main functions arguments:
211
+ if ($#ARGV > 1) { print "\n$usage\nToo many arguments \n\n"; exit 1; }
212
+ if ($#ARGV == 0) { print "\n$usage\nOutput Not Specified\n\n"; exit 1; }
213
+ if ($#ARGV == -1) { print "\n$usage\nInput and Output Not Specified\n\n";
214
+ exit 1; }
215
+
216
+ $InFile=$ARGV[0];
217
+ $OutFile=$ARGV[1];
218
+
219
+ if (! -r $InFile){
220
+ print "\n$usage\nInput file $InFile does not exist\n\n";
221
+ exit 1;
222
+ }
223
+
224
+ if ($OutFile eq "-"){
225
+ $OutFile = "";
226
+ } else {
227
+ $OutFile = " > ".$OutFile;
228
+ }
229
+
230
+ ($id=$InFile) =~ s:^.*/::;
231
+ $id =~ s/\.[^\.]*$//;
232
+
233
+ # Check the translation classes. If they exist, make an associative
234
+ # array to house them
235
+ if ($#Translate >= 0){
236
+ foreach my $tlate (@Translate){
237
+ $tlate =~ tr/a-z/A-Z/;
238
+ if ($Language eq "german" || $Language eq "spanish") {
239
+ $tlate =~ tr/\340-\377/\300-\337/; #Upper-Case accented letters
240
+ }
241
+ my @tl = split(/=/,$tlate);
242
+ $TranslateAArray{$tl[0]} = $tl[1];
243
+ }
244
+ }
245
+
246
+ # Check the equivalence classes. If they exist, make an associative
247
+ # array to house them
248
+ if ($#Equivs >= 0){
249
+ foreach my $equiv (@Equivs){
250
+ $equiv =~ tr/a-z/A-Z/;
251
+ if ($Language eq "german" || $Language eq "spanish") {
252
+ $equiv =~ tr/\340-\377/\300-\337/; #Upper-Case accented letters
253
+ }
254
+ my $alt;
255
+ ($alt = $equiv) =~ s/^/{ /;
256
+ $alt =~ s/$/ }/;
257
+ $alt =~ s:=: / :g;
258
+ foreach my $eq (split(/=/,$equiv)){
259
+ $EquivsAArray{$eq} = $alt;
260
+ }
261
+ }
262
+ }
263
+
264
+ open(FILE,"< $InFile") || die("cannot open input Callhome file $InFile");
265
+ #binmode FILE;
266
+
267
+ my $hubscr_path = "../hubscr/hubscr.pl";
268
+ die "ERROR: 'hubscr.pl' cannot be found, please edit 'chfilt.pl line 267 and set hubscr.pl path."if(! -e $hubscr_path);
269
+
270
+ #open(OUTPUT,"| sort -t \\ +0 -1 +1 -2 +3nb -4 $OutFile") ||
271
+ open(OUTPUT,"| perl $hubscr_path sortSTM $OutFile") ||
272
+ die("cannot open output file $OutFile");
273
+
274
+ ## make a place holder for the LUR reports
275
+ print OUTPUT ';; CATEGORY "0" "" ""'."\n";
276
+ print OUTPUT ';; LABEL "O" "Overall" "All Segments in the test set"'."\n";
277
+
278
+ # read in the file, deleting blank lines:
279
+ while (<FILE>){
280
+ s/\[\[[^]]*\]\]//g; #remove comments '[[words]]'
281
+
282
+ if ($_ !~ /^\s*$/ && $_ !~ /^#/){
283
+ if ($ReadMSstate){
284
+ s/^\S+\s+//;
285
+ }
286
+ push(@Trans,$_);
287
+ }
288
+ }
289
+ close (FILE);
290
+
291
+ # normalize the transcript so that each turn is on a line by itself
292
+ for (my $n=0; $n<=$#Trans; $n++){
293
+ if ($Trans[$n] =~ /^\s*\d+\.\d*\s+\d+\.\d*\s+[AB]\d*:/){
294
+ my $orig = $Trans[$n];
295
+ if ($ExpandContractions){
296
+ ### Scan the transcript looking for un-annotated non-possessive contractions
297
+ my $ct = $Trans[$n];
298
+ ### delete all tokens annotated as contractions
299
+ $ct =~ s/(<contraction\s+e_form=\"([^\"]+)\">([^ \t\n\r\f\)]+))//gi;
300
+ foreach my $ctt(split(/[\s\,\.\?]+/,$ct)){
301
+ print STDERR "Warning: Possible non-annotated contraction \"$ctt\"\n" if ($ctt =~ /\w'\w+/ && $ctt !~ /\w's$/);
302
+ }
303
+ }
304
+ while ($Trans[$n] =~ /(<contraction\s+e_form=\"([^\"]+)\">([^ \t\n\r\f\)]+))/i){
305
+ my ($tag, $rep, $token) = (quotemeta($1), $2, $3);
306
+ my $exp;
307
+ ($exp = $rep) =~ s/\[[^\[=]+=>/ /g;
308
+ $exp =~ s/\]//g;
309
+ $exp =~ s/^\s+//g;
310
+
311
+ # print "Found $tag $rep $token '$exp' ------------ in $Trans[$n]";
312
+ if ($ExpandContractions){
313
+ $Trans[$n] =~ s/$tag/$exp/;
314
+ } else {
315
+ $Trans[$n] =~ s/$tag/$token/;
316
+ }
317
+ die "Error: unable to expand the contraction\n" if ($orig eq $Trans[$n]);
318
+ $orig = $Trans[$n];
319
+ }
320
+ die "Error: Contraction not handled $Trans[$n]" if ($Trans[$n] =~ /<contrac/);
321
+ } else {
322
+ # print "no match $Trans[$n]";
323
+ if ($n == 0){
324
+ die("Illegal format, first line does not have a begin time, end time and channel");
325
+ }
326
+ chop($Trans[$n - 1]);
327
+ $Trans[$n - 1] = $Trans[$n - 1]." ".$Trans[$n];
328
+ splice(@Trans,$n,1);
329
+ $n--;
330
+ }
331
+ }
332
+
333
+ #print @Trans;
334
+
335
+ my @STMS = ();
336
+
337
+ ### Normalize the text
338
+ foreach $_ (@Trans){
339
+ #match the lines header
340
+ chomp;
341
+ die "Unable to strip the line header of '$_'" unless s/^(.*[AB][0-9]*):\s*//;
342
+ my $line_header = $1; #Store the header in a variable
343
+
344
+ tr/\011/ /; #change all tabs to spaces
345
+ s/ / /g; #multiple spaces go to one
346
+ s/^/ /; #add spaces at begining of line
347
+ s/$/ /; #put a space at the end of each line
348
+ s/\s\(\(/ (( /g; #add spaces around unintelligble markers
349
+ s/\)\)\s/ )) /g; #add spaces around unintelligble markers
350
+ if ($OptDel == 0){
351
+ s:<foreign\s+language=[^>]+>([^><]+)</foreign>:$1:gi;
352
+ } else {
353
+ s/\(\(\s*<foreign\s+language=\"[^"]+\">([^><]+)<\/foreign>\s*\)\)/\(\($1\)\)/gi;
354
+ s/<foreign\s+language=\"[^"]+\">([^><]+)<\/foreign>/\(\($1\)\)/gi;
355
+ }
356
+ #print "$_ here\n";
357
+ if ($Language ne "arabic") {
358
+ tr/a-z/A-Z/; #Upper-Case all letters
359
+ if ($Language eq "german" || $Language eq "spanish") {
360
+ tr/\340-\377/\300-\337/ #Upper-Case accented letters
361
+ }
362
+ }
363
+ s/\{[^{}]*\}//g; #remove non-speech vocal noises '{words}'
364
+
365
+ ### LANGUAGE Specific Normalizations
366
+ if ($Language eq "arabic") {
367
+ my $hes;
368
+ if ($OptDel == 0){
369
+ $hes="%\330\252\330\261\330\257\331\221\330\257";
370
+ } else {
371
+ $hes=" (%\330\252\330\261\330\257\331\221\330\257) ";
372
+ }
373
+ s/[% ]\330\243\331\207 /$hes /g; ## %>h
374
+ s/[% ]\330\245\331\212\331\207 /$hes /g; ## %<yh
375
+ s/[% ]\330\243\331\205 /$hes /g; ## >m
376
+ s/[% ]\330\243\331\210\331\210 /$hes /g; ## >ww
377
+ s/[% ]\331\207\330\247\331\212 /$hes /g; ## hAy
378
+ s/[% ]\331\205\331\207\331\205 /$hes /g; ## mhm
379
+
380
+ s/%*(\330\243\331\207\331\207) /$1 /g; ## Back Channel
381
+ s/%\330\243\330\254\331\206\330\250\331\212 / /g; ## Foreign lexeme
382
+ s/%\330\252\330\257\330\247\330\256\331\204.*%\330\252\330\257\330\247\330\256\331\204\\ / /g; ## End cross channel
383
+
384
+ ### Remove non speech markers
385
+ s/%\330\265\331\205\330\252\\* / /g; # silence
386
+ s/%\330\245\331\206\331\202\330\267\330\247\330\271\\* / /g; # pause symbol
387
+ s/%\330\266\330\254\331\221\330\251\\* / /g; # noise symbol
388
+ s/%\330\252\331\206\331\201\331\221\330\263\\* / /g; # breath symbol
389
+ s/%\330\263\330\271\330\247\331\204\\* / /g; # cough
390
+ s/%\330\266\330\255\331\203\\* / /g; # laugh
391
+ s/%\330\243\330\265\331\210\330\247\330\252\\* / /g; # people talk
392
+
393
+ # ## The LDC Transcripts have a special case encoded in them for
394
+ # ## foreign words with an attached definite article. The next few commands
395
+ # ## move the definite article into the foreign tag.
396
+ # s/\s(\S+)(<\S+)\s+(\S+)/ $2 $1$3/g;
397
+ # ## translate the arabic signle apostrophies to hyphens
398
+ # s/\254\s/- /g;
399
+ # s/\254$/- /g;
400
+ # s/\s\254/ -/g;
401
+ # ## Arabic Semi colon
402
+ # s/\s\273/ /g;
403
+ } elsif ($Language eq "english") {
404
+ ;
405
+ } elsif ($Language eq "japanese") {
406
+ $_ = &add_spaces_for_japanese_punctuation($_);
407
+ s/\241\242 /, /g; # Change the Japanese coma
408
+ s/\241\243 /. /g; # Change the Japanese periods
409
+ s/\241\244 /, /g; # Change the Japanese periods
410
+ s/\241\250 /; /g; # Change the Japanese semi-colon
411
+ s/\241\251 /? /g; # Change the Japanese question marks
412
+ s/\241\252 /! /g; # Change the Japanese exclaimation marks
413
+ s/\241\327 / /g; # Change the Japanese quotation mark
414
+ s/ \241\326/ /g; # Change the Japanese quotation mark
415
+ s/\241\343([\000-\177])/<$1/g; # Change the Japanese '<'
416
+ s/([\000-\177])\241\344/$1>/g; # Change the Japanese '>'
417
+ # Convert Japanese col and dia flags to alternations
418
+ s/@([^@\[\]]+)\[\[([^,\[\]]+)\s*,[^\[\]]+\]\]/ { $1 \/ $2 } /g;
419
+ } elsif ($Language eq "mandarin") {
420
+ while (s/(<[^_>]*)_/$1 /) { # Removes underlines from OOL items
421
+ ;
422
+ }
423
+ s/@([^@]+)@/$1/g; # Removes obviously the @'s !!!
424
+ s/\*([^\*]+)\*/$1/g; # Removes obviously the *'s !!!
425
+ }
426
+
427
+ ### Call Home filtering (General)
428
+
429
+ s/\-\-//g; #whatever they are??
430
+ s/[.,?!;]//g; #Remove normal punctuation
431
+ s/"//g; #Remove quotation marks
432
+ s/\#/ /g; #remove simultaneous speech markers '#'
433
+ s/\[\[[^]]*\]\]//g; #remove comments '[[words]]'
434
+ s/\[[^]]*\]//g; #remove other sounds '[words]'
435
+ s/\/\///g; #remove speech to someone else markers '//'
436
+ s/<\/*aside\/*>//g; #remove aside sgml tags
437
+
438
+ if ($ReadMSstate){
439
+ s/\^(\S)/$1/g; #remove proper name markers? '^'
440
+ s/\*(\S)/$1/g; #remove ??? name markers? '*'
441
+ s/\@(\S)/$1/g; #remove ??? name markers? '@'
442
+ s:<as/>[^<>]+</as>::ig; #remove asides
443
+ while ($_ =~ /~/){ # Deal with acronyms
444
+ s/~(\S) /$1 /;
445
+ s/~(\S\'[sS]) /$1 /; # Deal with a possessive acronym
446
+ s/~(\S)(\S)/$1 ~$2/;
447
+ }
448
+ }
449
+
450
+ s/\(\(\s*\)\)//g; #remove unintelligable speech with no words
451
+
452
+ ## Changes from new LDC transcription practices (Jan 2003)_
453
+ s/~([A-Z-a-z])/$1./g; #Change the spoken letters to the Hub4 form
454
+ s/\^//g; #Remove proper names
455
+
456
+
457
+ if ($OptDel == 1){
458
+ s/\(\s+/(/g; #Normalize the variablity in the LDC trans
459
+ s/\s+\)/)/g; #Normalize the variablity in the LDC trans
460
+ my $vb = 0;
461
+ my $iteration = 1;
462
+ print "Start $_\n" if ($vb);
463
+ my $loop_end = "xxxxxxxxxxxxxxxxx";
464
+
465
+ my $plainWord = "[^ \t\n\r\f\(\)\{\}]+";
466
+ my $optDelWord = "\\([^ \t\n\r\f\(\)\{\}]+\\)";
467
+ # my $wordSet = "($plainWord|$optDelWord)(\s+($plainWord|$optDelWord))*";
468
+
469
+ while ($_ =~ /\(\(.*\)\)/) {
470
+ # if the unintell is out side of a OOL marker, just delete them
471
+ s/\(\((\s*<[^>]+>\s*)\)\)/$1/;
472
+ print " Step 1 $_\n" if ($vb);
473
+
474
+ # handle unintelligle markers within OOL markers
475
+ s/\(\((\s*<[^>]+>\s*)([^\)]*)\)\)/$1 \(\($2\)\)/;
476
+ print " Step 2 $_\n" if ($vb);
477
+
478
+ #Change 1st unintelligable word, if its already optionally deletable
479
+ s/\(\(\s*($optDelWord)\s+(($plainWord|$optDelWord)(\s+($plainWord|$optDelWord))*\s*\)\))/ $1 \(\($2/g;
480
+ print " Step 3 $_\n" if ($vb);
481
+
482
+ #Change 1st unintelligable word, if its an alternate
483
+ s:\(\(\s*({[^{}]+})\s+(($plainWord|$optDelWord)(\s+($plainWord|$optDelWord))*\s*\)\)): \($1\) \(\($2:g;
484
+ print " Step 4 $_\n" if ($vb);
485
+
486
+ #Change 1st unintelligable word, if its a plain word
487
+ s/\(\(\s*($plainWord)\s+(($plainWord|$optDelWord)(\s+($plainWord|$optDelWord))*\s*\)\))/ \($1\) \(\($2/g;
488
+ print " Step 5 $_\n" if ($vb);
489
+
490
+ ## Change a single optionally deletable word
491
+ s/\(\(\s*($optDelWord)\s*\)\)/ $1 /g;
492
+ print " Step 8 $_\n" if ($vb);
493
+
494
+ #alternate single unintelligable with alternate
495
+ s/\(\(\s*({[^{}]+})\s*\)\)/ \($1\) /g;
496
+ print " Step 9 $_\n" if ($vb);
497
+
498
+ #alternate single unintelligable words
499
+ s/\(\(\s*($plainWord)\s*\)\)/ \($1\) /g;
500
+ print " Step A $_\n" if ($vb);
501
+
502
+ # remove empty unintellegible markers
503
+ s/\(\(\s*\)\)//g;
504
+ $iteration ++;
505
+
506
+ if ($_ eq $loop_end){
507
+ print STDERR "Warning: unable to fully alternate an unitelligible marker\n".
508
+ " $_\n";
509
+ last;
510
+ }
511
+ if ($iteration > 100){
512
+ die "Unable to alternate an unitelligible marker '$_'\n";
513
+ }
514
+ # Remember what the last line was so that We don't get it an infinite loop
515
+ $loop_end = $_;
516
+ print " End $_\n" if ($vb);
517
+ }
518
+ } else {
519
+ # print "Delete (( $_\n";
520
+ s/\s\(\(/ /g; #Strip the unintelligible markers
521
+ s/\)\)\s/ /g; #Strip the unintelligible markers
522
+ # print " $_\n";
523
+ }
524
+
525
+ if (! $OptDel){
526
+ s/<\s*\S+\s+([^<>]*)>/$1/g; #remove out-of-language speech markers
527
+ s/<[^<>]*>//g; #remove out-of-language speech markers
528
+ } else {
529
+ while ($_ =~ /(<\s*\S+\s+)([^<>]*)>/) {
530
+ my ($otxt, $head) = ($2, $1);
531
+ my $txt = $otxt;
532
+ $txt =~ s/^\s+//;;
533
+ $txt =~ s/\s+$//;;
534
+ my $new= "";
535
+ foreach my $w(split(/\s+/,$txt)){
536
+ if ($w !~ /^\(.+\)$/){
537
+ if ($new eq ""){
538
+ $new = "(".$w.")";
539
+ } else {
540
+ $new .= " (".$w.")";
541
+ }
542
+ } else {
543
+ $new .= " $w";
544
+ }
545
+ }
546
+ if ( ($_ =~ s/${head}[^>]*>/$new/) != 1){
547
+ die("OptDel substitution of non-language marker failed\n".
548
+ " text: $_ head: '$head'\n otxt: '$otxt'\n new: '$new'".
549
+ "\n merge: '${head}${otxt}>'");
550
+ }
551
+ }
552
+ ### delete noise tags. These are new as of 1/20/2004
553
+ s/<[^ \t\n\r\f<>]+>//g;
554
+ }
555
+
556
+ ### Language Specific Filters
557
+
558
+ # SPANISH
559
+ if ($Language eq "spanish") {
560
+ y/\240-\277//d; #remove spanish punctuation
561
+ s/\*\*//g; #words marked with "**" (as neologisms or unknown
562
+ # 'words')
563
+ s/\+//g; #words marked with "++" (mispronunciations given
564
+ # in correct orthography)
565
+
566
+ # map the list of hesitiation's
567
+ s:%::g; # remove all hesitation markers (maybe illegal ones!)
568
+ # insert all hesitation markers (maybe missed ones!)
569
+ s/ AAA / $HES /g;
570
+ s/ EEE / $HES /g;
571
+ s/ III / $HES /g;
572
+ s/ MMM / $HES /g;
573
+ s/ EMM / $HES /g;
574
+ s/ AMM / $HES /g;
575
+ s/ IMM / $HES /g;
576
+ s/ EH / $HES /g;
577
+ s/ MMH / $HES /g;
578
+ s/ OH / $HES /g;
579
+ s/ UH / $HES /g;
580
+ s/ EY / $HES /g;
581
+ s/ UY / $HES /g;
582
+ s/ PSS / $HES /g;
583
+ s/ HM / $HES /g;
584
+ s/ UF / $HES /g;
585
+ s/ SHH / $HES /g;
586
+ s/ PFF / $HES /g;
587
+ s/ OY / $HES /g;
588
+ s/ HA / $HES /g;
589
+ s/ AH / $HES /g;
590
+ }
591
+
592
+ # GERMAN
593
+ if ($Language eq "german") {
594
+
595
+ s/\&//g; #remove proper name marker
596
+ s/\+//g; #words marked with "++" (mispronunciations given
597
+ # in correct orthography)
598
+ s/\*\*//g; #words marked with "**" (as neologisms
599
+ # or unknown 'words')
600
+
601
+ s:%::g; # remove all hesitation markers (maybe illegal ones!)
602
+ # insert all hesitation markers (maybe missed ones!)
603
+
604
+ s/ �H / $HES /g;
605
+ s/ MM / $HES /g;
606
+ s/ �HM / $HES /g;
607
+ s/ HM / $HES /g;
608
+ s/ HA / $HES /g;
609
+ s/ EI / $HES /g;
610
+ s/ UH / $HES /g;
611
+ s/ H� / $HES /g;
612
+ s/ HO / $HES /g;
613
+ s/ UFF / $HES /g;
614
+ s/ OI / $HES /g;
615
+ s/ HUH / $HES /g;
616
+ s/ BAH / $HES /g;
617
+ s/ UI / $HES /g;
618
+ }
619
+
620
+
621
+ # ARABIC
622
+ if ($Language eq "arabic") {
623
+
624
+ s/\&//g; #remove proper name the marker
625
+ s/\s\+(\S+)\+\s/ $1 /; #Remove the plus markers
626
+ # s:%\S+\s::g; # remove all hesitation markers (maybe illegal ones!)
627
+ s/\*\*//g; #words marked with "**" (as neologisms
628
+ # or unknown 'words')
629
+ s/$/ /; ## Add a space at the end of the line
630
+ s/ / /; ## Add double spaces
631
+
632
+ # insert all hesitation markers (maybe missed ones!)
633
+ # s/ ah / $HES /g;
634
+ # s/ E / $HES /g;
635
+ # s/ M / $HES /g;
636
+ # s/ mhm / $HES /g;
637
+ # s/ ha / $HES /g;
638
+ # s/ uh / $HES /g;
639
+ # s/ yA / $HES /g;
640
+ # s/ aha / $HES /g;
641
+ # s/ yaa / $HES /g;
642
+ # s/ hm / $HES /g;
643
+ # s/ hum / $HES /g;
644
+ # s/ Ah / $HES /g;
645
+ # s/ ayyO / $HES /g;
646
+ # s/ Eyy / $HES /g;
647
+ # s/ yuu / $HES /g;
648
+ # s/ ih / $HES /g;
649
+ # s/ yO / $HES /g;
650
+ # s/ O / $HES /g;
651
+ # s/ wAw / $HES /g;
652
+ # s/ hi / $HES /g;
653
+ # s/ Hay / $HES /g;
654
+ # s/ yOO / $HES /g;
655
+ # s/ OhO / $HES /g;
656
+ # s/ hE / $HES /g;
657
+ # ### Script equivalences
658
+ # s/ \302\347 / $HES /g;
659
+ # s/ \305\352\347 / $HES /g;
660
+ # s/ \305\352\352\347 / $HES /g;
661
+ # s/ \315\351 / $HES /g;
662
+ # s/ \345 / $HES /g;
663
+ # s/ \307\350 / $HES /g;
664
+ # s/ \307\350\347\350 / $HES /g;
665
+ # s/ \307\347 / $HES /g;
666
+ # s/ \307\347\307 / $HES /g;
667
+ # s/ \307\352\350 / $HES /g;
668
+ # s/ \347\351 / $HES /g;
669
+ # s/ \347\307 / $HES /g;
670
+ # s/ \347\351 / $HES /g;
671
+ # s/ \347\345 / $HES /g;
672
+ # s/ \347\345 / $HES /g;
673
+ # s/ \305\347 / $HES /g;
674
+ # s/ \345\345 / $HES /g;
675
+ # s/ \307\347 / $HES /g;
676
+ # s/ \350\307\350 / $HES /g;
677
+ # s/ \352\307\347 / $HES /g;
678
+ # s/ \352\350 / $HES /g;
679
+ # s/ \352\350\350 / $HES /g;
680
+ # s/ \352\307 / $HES /g;
681
+ # s/ \352\347 / $HES /g;
682
+ }
683
+
684
+ # MANDARIN
685
+ if ($Language eq "mandarin") {
686
+ s/\+//g; #remove non-standard representation marker
687
+ s/\&//g; #remove some the marker
688
+ s/\243[\254\255] / /g; # Remove Japanese punctuation
689
+
690
+ s/\s%(\S)/ $1/g; # Delete the all the percent signs at word head
691
+ s/\s\(\%/ (/g; # Delete the all the percent signs at word head of unclear
692
+ s/%\s/ /g; # Delete the all the percent signs at word tail
693
+
694
+ # NOTE: Cannot remove all hesitation markers because some "%" are used
695
+ # in the text (I think)
696
+ # So we will just filter the known hesitation markers.
697
+ s/\s��\s/ $HES /g;
698
+ s/\s��\s/ $HES /g;
699
+ s/\s��\s/ $HES /g;
700
+ s/\s��\s/ $HES /g;
701
+ s/\s��\s/ $HES /g;
702
+ }
703
+
704
+ # JAPANESE
705
+ if ($Language eq "japanese") {
706
+ s/\+//g; #remove non-standard representation marker
707
+ s/\=/\-/g; #change frag= to frag-
708
+ s/\241[\241-\256] / /g; # Remove Japanese punctuation
709
+ }
710
+
711
+ if ($Language eq "english") {
712
+ s/\&//g; #remove proper name the marker
713
+ s/\*\*//g; #words marked with "**" (as neologisms
714
+ # or unknown 'words')
715
+ s/\*//g; #words marked with "*" idiosyncratic words
716
+ # or unknown 'words')
717
+ s/\+//g; #words marked with "++" (mispronun-
718
+ # ciations given in correct orthography)
719
+ s/@//g; # Spoken acronyms
720
+ ### Mapp the hesitations
721
+ s/[\s\(][%]*(UH|UM|EH|MM|AH|HM|HUH|HA|ER|OOF|HEE|ACH|EEE|EW)[\s\)]/ $HES /g;
722
+ if ($ReadMSstate){
723
+ #### Commented out because this should be changed in SPINE
724
+ #### s/[\s\(][%]*(OH|AW)[\s\)]/ $HES /g;
725
+ s/[\s\(][%]*(MHM)[\s\)]/ $1 /g;
726
+ }
727
+ }
728
+
729
+ # This has to be done AFTER ALL THE PROCEEDING STEPS to alternate any fragment words
730
+ if ($OptDel){
731
+ s/(\S+)-(\S+)[-=]\s/ $1 \($2-\) /g; #put in alternates for fragments
732
+ s/(\S*)[-=]\s/ \($1-\) /g; #put in alternates for fragments
733
+ s/\s[-=](\S*)/ \(-$1\) /g; #put in alternates for fragments
734
+ } else {
735
+ s/(\S*)[-=]\s/ $1- /g; #put in alternates for fragments
736
+ s/\s[-=](\S*)/ -$1 /g; #put in alternates for fragments
737
+ }
738
+ s/ +/ /g;
739
+ if ($#Translate >= 0){
740
+ $_ = &Map_AArray($_,\%TranslateAArray);
741
+ }
742
+ if ($#Equivs >= 0){
743
+ $_ = &Map_AArray($_,\%EquivsAArray);
744
+ }
745
+ if ($AltHyphens) {
746
+ $_ = &AlternateHyphenWords($_);
747
+ }
748
+
749
+ ### delete any emtpy optionally deletable words
750
+ if ($OptDel){ s/\(\)//g; }
751
+
752
+ my($bt, $et, $spkr) = split(/\s+/,$line_header);
753
+ my $chan;
754
+ ($chan = $spkr) =~ s/[0-9]$//;
755
+ if (&in_range($bt, $et) && ($KeepEmptyLines || $_ !~ /^\s*$/)){
756
+ if ($Format eq "stm"){
757
+ push @STMS, sprintf "%s %s %s %s %6.2f <O> %s\n",$id,makeChannel($chan),$id."_".$spkr,$bt,$et,$_;
758
+ } elsif ($Format eq "pem"){
759
+ printf OUTPUT "%s %s %s %s %s\n",$id,makeChannel($chan),"unknown_speaker",$bt,$et;
760
+ }
761
+ }
762
+ }
763
+
764
+ sub makeChannel{
765
+ my ($chan) = @_;
766
+ if ($ChannelsTo eq "numbers") {
767
+ $chan =~ s/a/1/i;
768
+ $chan =~ s/b/2/i;
769
+ } elsif ($ChannelsTo eq "letters") {
770
+ $chan =~ s/1/A/i;
771
+ $chan =~ s/2/B/i;
772
+ } elsif ($ChannelsTo eq "asis") {
773
+ ;
774
+ } else {
775
+ die "Error: unknown Channel conversion $ChannelsTo";
776
+ }
777
+ $chan;
778
+ }
779
+
780
+ sub MIN{
781
+ my(@a) = @_;
782
+ my($min) = 99e9;
783
+
784
+ while ($#a >= 0){
785
+ # print " $a[0]\n";
786
+ $min = $a[0] if ($min > $a[0]);
787
+ splice(@a,0,1);
788
+ }
789
+ $min;
790
+ }
791
+
792
+ if ($Format eq "stm"){
793
+ my (%lastStmEnd, %lastStmEndId, %lastStmEndIndex, $nt);
794
+ ### Pad the STMs segments with silence if you got it
795
+ if ($PadSilence >= 0){
796
+ for (my $i=0; $i<@STMS; $i++){
797
+ # print "STM[$i] = $STMS[$i]";
798
+ my ($id, $chan, $spkr, $bt, $et, $lur, $text) = split(/\s+/,$STMS[$i],7);
799
+ if (! defined($lastStmEnd{$chan})){
800
+ # print "Set \$lastStmEnd{$chan} = $NewBeginTime;\n";
801
+ $lastStmEnd{$chan} = $NewBeginTime;
802
+ $lastStmEndId{$chan} = $id;
803
+ $lastStmEndIndex{$chan} = $i;
804
+ }
805
+ if ($lastStmEnd{$chan} < $bt){
806
+ my $shift = MIN(($bt - $lastStmEnd{$chan}) / 2.0, $PadSilence);
807
+ if ($lastStmEndIndex{$chan} < $i){
808
+ $nt = sprintf("%.2f", $lastStmEnd{$chan} + $shift);
809
+ # print "fix $nt $STMS[$lastStmEndIndex{$chan}] ";
810
+ die "Can't fix silence pad time of previous line" unless ($STMS[$lastStmEndIndex{$chan}] =~ s/^(\S+\s+\S+\s+\S+\s+\S+\s+)\S+/$1$nt/);
811
+ # print "-> $STMS[$lastStmEndIndex{$chan}]\n";
812
+ }
813
+ $nt = sprintf("%.2f",$bt - $shift);
814
+ die "Can't fix silence pad time" unless ($STMS[$i] =~ s/^(\S+\s+\S+\s+\S+\s+)\S+/$1$nt/);
815
+ }
816
+ $lastStmEnd{$chan} = $et;
817
+ $lastStmEndIndex{$chan} = $i;
818
+ # print " \$lastStmEnd{$chan} = $et\n";
819
+ }
820
+ foreach my $chan(sort(keys %lastStmEnd)){
821
+ my ($id, $ccchan, $spkr, $bt, $et, $lur, $text) = split(/\s+/,$STMS[$lastStmEndIndex{$chan}],7);
822
+ # print "End $STMS[$lastStmEndIndex{$chan}]";
823
+ if ($lastStmEnd{$chan} < $NewEndTime){
824
+ my $shift = MIN(($NewEndTime - $lastStmEnd{$chan}) / 2.0, $PadSilence);
825
+ $nt = $lastStmEnd{$chan} + $shift;
826
+ die "Can't fix silence pad time" unless ($STMS[$lastStmEndIndex{$chan}] =~ s/^(\S+\s+\S+\s+\S+\s+\S+\s+)\S+/$1$nt/);
827
+ # print " end now $STMS[$lastStmEndIndex{$chan}]\n";
828
+ }
829
+ }
830
+ }
831
+ undef %lastStmEnd;
832
+ undef %lastStmEndId;
833
+
834
+ ## Smooth the segments
835
+ if ($SmoothSegments >= 0){
836
+ for (my $i=0; $i<@STMS; $i++){
837
+ my ($id, $chan, $spkr, $bt, $et, $lur, $text) = split(/\s+/,$STMS[$i],7);
838
+ if (! defined($lastStmEnd{$chan})){
839
+ $lastStmEnd{$chan} = $NewBeginTime;
840
+ $lastStmEndId{$chan} = $id;
841
+ $lastStmEndIndex{$chan} = $i;
842
+ }
843
+ my $change = 0;
844
+ if ($lastStmEnd{$chan} > $bt - $SmoothSegments && $lastStmEndIndex{$chan} < $i){
845
+ my ($lid, $lchan, $lspkr, $lbt, $let, $llur, $ltext) = split(/\s+/,$STMS[$lastStmEndIndex{$chan}],7);
846
+ if ($id eq $lid && $chan eq $lchan && $spkr eq $lspkr && $lur eq $llur){
847
+ chomp $ltext;
848
+ chomp $text;
849
+ $STMS[$lastStmEndIndex{$chan}] =
850
+ "$id $chan $spkr $lbt $et $lur $ltext $text\n";
851
+ splice (@STMS, $i, 1);
852
+ $i --;
853
+ $change = 1;
854
+ }
855
+ }
856
+ $lastStmEnd{$chan} = $et;
857
+ if (! $change){
858
+ $lastStmEndIndex{$chan} = $i;
859
+ }
860
+ }
861
+ }
862
+ undef %lastStmEnd;
863
+ undef %lastStmEndId;
864
+
865
+ ## Smooth the segments
866
+ if ($ExcludeOverlap){
867
+ for (my $i=0; $i<@STMS; $i++){
868
+ # print "STM[$i] = $STMS[$i]";
869
+ my ($id, $chan, $spkr, $bt, $et, $lur, $text) = split(/\s+/,$STMS[$i],7);
870
+ if (! defined($lastStmEnd{$chan})){
871
+ $lastStmEnd{$chan} = $NewBeginTime;
872
+ $lastStmEndId{$chan} = $id;
873
+ $lastStmEndIndex{$chan} = $i;
874
+ }
875
+ my $change = 0;
876
+ if ($lastStmEnd{$chan} > $bt && $lastStmEndIndex{$chan} < $i){
877
+ my ($lid, $lchan, $lspkr, $lbt, $let, $llur, $ltext) = split(/\s+/,$STMS[$lastStmEndIndex{$chan}],7);
878
+ if ($id eq $lid && $chan eq $lchan){
879
+ chomp $ltext;
880
+ $STMS[$lastStmEndIndex{$chan}] =
881
+ "$id $chan excluded_region $lbt $et $lur ignore_time_segment_in_scoring\n";
882
+ splice (@STMS, $i, 1);
883
+ $i --;
884
+ $change = 1;
885
+ }
886
+ }
887
+ $lastStmEnd{$chan} = $et;
888
+ if (! $change){
889
+ $lastStmEndIndex{$chan} = $i;
890
+ }
891
+ }
892
+ }
893
+ undef %lastStmEnd;
894
+ undef %lastStmEndId;
895
+
896
+ ## Add the intersegment gaps
897
+ if ($AddInterSegGap){
898
+ for (my $i=0; $i<@STMS; $i++){
899
+ my ($id, $chan, $spkr, $bt, $et, $lur, $text) = split(/\s+/,$STMS[$i],7);
900
+ if (! defined($lastStmEnd{$chan})){
901
+ $lastStmEnd{$chan} = $NewBeginTime;
902
+ $lastStmEndId{$chan} = $id
903
+ }
904
+ if ($lastStmEnd{$chan} < $bt - 0.01){
905
+ # if (0){
906
+ splice (@STMS, $i, 0, sprintf("%s %s %s %s %6.2f <O> %s\n",$id,$chan,
907
+ "${id}_${chan}_".
908
+ "inter_segment_gap",
909
+ $lastStmEnd{$chan},$bt,""));
910
+ $i++;
911
+ }
912
+ $lastStmEnd{$chan} = $et;
913
+ }
914
+ foreach my $chan(sort(keys %lastStmEnd)){
915
+ if ($lastStmEnd{$chan} < $NewEndTime - 0.01){
916
+ push(@STMS, sprintf("%s %s %s %s %6.2f <O> %s\n",$lastStmEndId{$chan},$chan,
917
+ "${id}_${chan}_inter_segment_gap",
918
+ $lastStmEnd{$chan},$NewEndTime,""));
919
+ }
920
+ }
921
+ }
922
+ }
923
+ print OUTPUT @STMS;
924
+ close OUTPUT;
925
+ exit 0;
926
+
927
+ ###############################################################################
928
+ #### ####
929
+ #### END OF MAIN PROGRAM ####
930
+ #### ####
931
+ ###############################################################################
932
+
933
+
934
+ ####
935
+ #### Return true if the passed in begin and end times are within the
936
+ #### specified range of output times. If not return false.
937
+ #### Inputs: - Argument 0: The begin time
938
+ #### - Argument 1: The end time
939
+ #### Outputs: - Return true if:
940
+ #### * the global variables $NewBeginTime or $NewEndTime
941
+ #### * are set, and the begin and end times are with their
942
+ #### * respective ranges
943
+ #### OR
944
+ #### * neither global variables are defined.
945
+ sub in_range{
946
+ my ($bt,$et) = @_;
947
+ my $do_prnt = 0;
948
+ if (defined($NewBeginTime) && defined($NewEndTime)) {
949
+ if (($bt >= $NewBeginTime || &eqdelta($bt,$NewBeginTime,0.5)) &&
950
+ ($et <= $NewEndTime || &eqdelta($et,$NewEndTime,0.5))) {
951
+ $do_prnt = 1;
952
+ }
953
+ } elsif (defined($NewBeginTime)) {
954
+ if ($bt >= $NewBeginTime ||
955
+ &eqdelta($bt,$NewBeginTime,0.5)) {
956
+ $do_prnt = 1;
957
+ }
958
+ } elsif (defined($NewEndTime)) {
959
+ if ($et <= $NewEndTime || &eqdelta($et,$NewEndTime,0.5)) {
960
+ $do_prnt = 1;
961
+ }
962
+ } else {
963
+ $do_prnt = 1;
964
+ }
965
+ $do_prnt;
966
+ }
967
+
968
+
969
+ ####
970
+ #### Compare two real numbers, they're equal if the absolute value of the
971
+ #### difference is less than delta
972
+ #### Inputs: - Argument 0: real number 1.
973
+ #### - Argument 1: real number 2.
974
+ #### - Argument 2: The delta.
975
+ #### Outputs: - True if they are equal, False if they are not
976
+ sub eqdelta {
977
+ my($v1,$v2,$del) = @_;
978
+ if ($v1 < $v2) {
979
+ $v2 - $v1 < $del;
980
+ } else {
981
+ $v1 - $v2 < $del;
982
+ }
983
+ }
984
+
985
+ sub add_spaces_for_japanese_punctuation {
986
+ $_ = $_[0];
987
+ chomp;
988
+ my $first = 0;
989
+ my $c1 = "";
990
+ my $lc = "";
991
+ my $out = "";
992
+
993
+ while (length($_) > 0){
994
+ s/^(.)//;
995
+ $c1 = $1;
996
+ if ($c1 =~ /^[\177-\377]/){
997
+ if (!$first) { $first = 1; } else { $first = 0; }
998
+ }
999
+ $out = $out.$c1;
1000
+ if (!$first && ($lc.$c1) =~ /^\241[\241-\270\272\273\275-\377]$/) {
1001
+ $out = $out." ";
1002
+ }
1003
+ $lc = $c1;
1004
+ }
1005
+ $out."\n";
1006
+ }
1007
+
1008
+ sub Map_AArray{
1009
+ $_ = $_[0];
1010
+ my $AArray = $_[1];
1011
+ my $out = "";
1012
+ my $word = "";
1013
+ foreach $word (split){
1014
+ if ($AArray->{$word} !~ /^$/){
1015
+ $out .= " ".$AArray->{$word};
1016
+ } else {
1017
+ $out .= " ".$word;
1018
+ }
1019
+ }
1020
+ $out .= "\n";
1021
+ $out;
1022
+ }
1023
+
1024
+ sub AlternateHyphenWords{
1025
+ $_ = $_[0];
1026
+ my $out = "";
1027
+ my $word = "";
1028
+ my $x;
1029
+ my $y;
1030
+ my $z;
1031
+ foreach $word (split){
1032
+ if ($word =~ /[A-Za-z][_-][A-Za-z]/){
1033
+ ($x=$word) =~ s/[_-]//g;
1034
+ ($y=$word) =~ s/[_-]/ /g;
1035
+ ($z=$word) =~ s/[_-]/-/g;
1036
+ $word = "{ ".$y." / ".$x." / ".$z." }";
1037
+ }
1038
+ $out .= " ".$word;
1039
+ }
1040
+ $out .= "\n";
1041
+ $out;
1042
+ }
SCTK/src/chfilt/makefile ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # **********************************************************
2
+ # Makefile for rfilter1 Directory
3
+ # **********************************************************
4
+ SHELL = /bin/sh
5
+ PREFIX=/home/userube/mozilla/zz__temp_5_rover/SCTK
6
+ bindir = $(PREFIX)/bin
7
+ T=../test_suite
8
+
9
+ all: chfilt.pl
10
+
11
+ chfilt.pl:
12
+ chmod +x chfilt.pl
13
+
14
+ setTests:
15
+ ./chfilt.pl -m -l english $(T)/testmss.in -- - > $(T)/testmss.stm
16
+ ./chfilt.pl -C numbers -m -l english $(T)/testmss.in -- - > $(T)/testmss.numbers.stm
17
+ ./chfilt.pl -l english -i -b 0 -e 999999 -k $(T)/test.txt -- - > $(T)/test.txt.-optdel.stm
18
+ ./chfilt.pl -d -l english -i -b 0 -e 999999 -k $(T)/test.txt -- - > $(T)/test.txt.stm
19
+ ./chfilt.pl -c -l english -i -b 0 -e 999999 -k $(T)/test.txt -- - > $(T)/test.txt.-contexp.stm
20
+ ./chfilt.pl -c -l arabic -i -b 0 -e 999999 -d -k $(T)/test.arb2004.txt -- - > $(T)/test.arb2004.txt.stm
21
+ ./chfilt.pl -c -l mandarin -i -b 0 -e 999999 -d -k $(T)/test.man2004.txt -- - > $(T)/test.man2004.txt.stm
22
+
23
+ check: all
24
+ @echo "Testing chfilt.pl"
25
+ ./chfilt.pl -m -l english $(T)/testmss.in -- - | diff - $(T)/testmss.stm
26
+ ./chfilt.pl -C numbers -m -l english $(T)/testmss.in -- - | diff - $(T)/testmss.numbers.stm
27
+ ./chfilt.pl -l english -i -b 0 -e 999999 -k $(T)/test.txt -- - | diff - $(T)/test.txt.-optdel.stm
28
+ ./chfilt.pl -d -l english -i -b 0 -e 999999 -k $(T)/test.txt -- - | diff - $(T)/test.txt.stm
29
+ ./chfilt.pl -c -l english -i -b 0 -e 999999 -k $(T)/test.txt -- - | diff - $(T)/test.txt.-contexp.stm
30
+ ./chfilt.pl -c -l arabic -i -b 0 -e 999999 -d -k $(T)/test.arb2004.txt -- - | diff - $(T)/test.arb2004.txt.stm
31
+ ./chfilt.pl -c -l mandarin -i -b 0 -e 999999 -d -k $(T)/test.man2004.txt -- - | diff - $(T)/test.man2004.txt.stm
32
+ @echo " chfilt.pl tests successfully completed"
33
+
34
+ install: all
35
+ cp chfilt.pl $(DESTDIR)$(bindir)
36
+
37
+ clean:
38
+
39
+ distclean: clean
40
+ $(RM) -r *~ makefile
SCTK/src/chfilt/makefile.in ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # **********************************************************
2
+ # Makefile for rfilter1 Directory
3
+ # **********************************************************
4
+ SHELL = /bin/sh
5
+ PREFIX=
6
+ bindir = $(PREFIX)/bin
7
+ T=../test_suite
8
+
9
+ all: chfilt.pl
10
+
11
+ chfilt.pl:
12
+ chmod +x chfilt.pl
13
+
14
+ setTests:
15
+ ./chfilt.pl -m -l english $(T)/testmss.in -- - > $(T)/testmss.stm
16
+ ./chfilt.pl -C numbers -m -l english $(T)/testmss.in -- - > $(T)/testmss.numbers.stm
17
+ ./chfilt.pl -l english -i -b 0 -e 999999 -k $(T)/test.txt -- - > $(T)/test.txt.-optdel.stm
18
+ ./chfilt.pl -d -l english -i -b 0 -e 999999 -k $(T)/test.txt -- - > $(T)/test.txt.stm
19
+ ./chfilt.pl -c -l english -i -b 0 -e 999999 -k $(T)/test.txt -- - > $(T)/test.txt.-contexp.stm
20
+ ./chfilt.pl -c -l arabic -i -b 0 -e 999999 -d -k $(T)/test.arb2004.txt -- - > $(T)/test.arb2004.txt.stm
21
+ ./chfilt.pl -c -l mandarin -i -b 0 -e 999999 -d -k $(T)/test.man2004.txt -- - > $(T)/test.man2004.txt.stm
22
+
23
+ check: all
24
+ @echo "Testing chfilt.pl"
25
+ ./chfilt.pl -m -l english $(T)/testmss.in -- - | diff - $(T)/testmss.stm
26
+ ./chfilt.pl -C numbers -m -l english $(T)/testmss.in -- - | diff - $(T)/testmss.numbers.stm
27
+ ./chfilt.pl -l english -i -b 0 -e 999999 -k $(T)/test.txt -- - | diff - $(T)/test.txt.-optdel.stm
28
+ ./chfilt.pl -d -l english -i -b 0 -e 999999 -k $(T)/test.txt -- - | diff - $(T)/test.txt.stm
29
+ ./chfilt.pl -c -l english -i -b 0 -e 999999 -k $(T)/test.txt -- - | diff - $(T)/test.txt.-contexp.stm
30
+ ./chfilt.pl -c -l arabic -i -b 0 -e 999999 -d -k $(T)/test.arb2004.txt -- - | diff - $(T)/test.arb2004.txt.stm
31
+ ./chfilt.pl -c -l mandarin -i -b 0 -e 999999 -d -k $(T)/test.man2004.txt -- - | diff - $(T)/test.man2004.txt.stm
32
+ @echo " chfilt.pl tests successfully completed"
33
+
34
+ install: all
35
+ cp chfilt.pl $(DESTDIR)$(bindir)
36
+
37
+ clean:
38
+
39
+ distclean: clean
40
+ $(RM) -r *~ makefile
SCTK/src/ctmValidator/makefile ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ SHELL = /bin/sh
2
+ PREFIX=/home/userube/mozilla/zz__temp_5_rover/SCTK
3
+ bindir = $(PREFIX)/bin
4
+
5
+ all: ctmValidator.pl
6
+
7
+ rttmValidator.pl:
8
+ chmod +x ctmValidator.pl
9
+
10
+ check: all
11
+ (cd test_suite; $(SHELL) RunTest.sh ../ctmValidator.pl)
12
+
13
+ install: all
14
+ cp ctmValidator.pl $(DESTDIR)$(bindir)
15
+
16
+ clean:
17
+
18
+ distclean: clean
19
+ $(RM) -r *~ makefile
SCTK/src/hamzaNorm/hamzaNorm.pl ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env perl
2
+
3
+ use strict;
4
+
5
+ my $Version="1.0";
6
+
7
+ #####
8
+ # Version 1.0 Released August 25, 2004
9
+ # - Initial Release
10
+
11
+ my $Usage="Usage: hamzaNorm.pl [ -i fmt ] Infile|- OutFile|-\n".
12
+ "Version: $Version\n".
13
+ "Desc: hamzaNorm normalizes the hamza in the initial position of the word to be a\n".
14
+ " consistent form. In the Buckwalter normalization scheme, the initial letters\n".
15
+ " 'A', '<', '>' and '|' are all translated to 'A'".
16
+ "Options:\n".
17
+ " -i fmt Set the input file formant to 'fmt'. The possible choices are:\n".
18
+ " txt -> plain text, the default\n".
19
+ " ctm -> CTM format, ignores all but the 5th column, and if\n".
20
+ " a division occurs and a confidence score is present,\n".
21
+ " the confidence score is copied to all parts.\n".
22
+ " stm -> STM format, change only the text field of the stm record\n".
23
+ "\n";
24
+
25
+ use Getopt::Long;
26
+ my ($InFmt) = undef;
27
+ my $result = GetOptions ("i:s" => \$InFmt);
28
+ die "Aborting:\n$Usage\n:" if (!$result);
29
+
30
+ if (defined($InFmt)) {
31
+ die("$Usage\n\nError: Undefined input format '$InFmt'")
32
+ if ($InFmt !~ /^(txt|ctm|stm)$/);
33
+ } else {
34
+ $InFmt = "txt";
35
+ }
36
+
37
+ #### The main functions arguments:
38
+ die "$Usage\nToo many arguments" if ($#ARGV > 1);
39
+ die "$Usage\nOutput Not Specified" if ($#ARGV == 0);
40
+ die "$Usage\nInput and Output Not Specified" if ($#ARGV == -1);
41
+
42
+ my $InFile=$ARGV[0];
43
+ my $OutFile=$ARGV[1];
44
+ die("$Usage\nError: Input file $InFile does not exist\n")
45
+ if ($InFile ne "-" && ! -r $InFile);
46
+
47
+ open(IN, "$InFile") || die "Unable to open trans-file $InFile";
48
+ open(OUT, ">$OutFile") || die "Unable to open new-trans-file $OutFile";
49
+
50
+ while (<IN>){
51
+ chomp;
52
+ if ($InFmt eq "txt"){
53
+ print OUT normalize($_)."\n";
54
+ } elsif ($InFmt eq "ctm"){
55
+ if ($_ =~ /^(\;\;|\#)/){
56
+ print OUT $_."\n";
57
+ next;
58
+ }
59
+ s/^(\s+)//;
60
+ my $prefix = (defined($1) ? $1 : "");
61
+ my @ctm = split(/(\s+)/,$_);
62
+ $ctm[8] = normalize($ctm[8]);
63
+ print OUT $prefix.join("", @ctm)."\n";
64
+ } elsif ($InFmt eq "stm"){
65
+ if ($_ =~ /^(\;\;|\#)/){
66
+ print OUT $_."\n";
67
+ next;
68
+ }
69
+ s/^(\s+)//;
70
+ my $prefix = (defined($1) ? $1 : "");
71
+ my @stm = split(/(\s+)/,$_, 7);
72
+ if ($stm[10] =~ /^<[^<>]*>$/){
73
+ $stm[12] = normalize($stm[12]);
74
+ } else {
75
+ $stm[10] .= join("",splice(@stm,11,2));
76
+ $stm[10] = normalize($stm[10]);
77
+ }
78
+ print OUT $prefix.join("", @stm)."\n";
79
+ } else {
80
+ die "Error: unknown input format '$InFmt'\n$Usage\n";
81
+ }
82
+ }
83
+
84
+ close IN; close OUT;
85
+ exit 0;
86
+
87
+ sub normalize{
88
+ my ($text) = @_;
89
+ $text = " ".$text;
90
+ $text =~ s/ (\330\242|\330\243|\330\245|\330\247)/ \330\247/g;
91
+ $text =~ s/^ //;
92
+ $text;
93
+ }
94
+
95
+
SCTK/src/hamzaNorm/makefile ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # **********************************************************
2
+ # Makefile for rfilter1 Directory
3
+ # **********************************************************
4
+ SHELL = /bin/sh
5
+ PREFIX=/home/userube/mozilla/zz__temp_5_rover/SCTK
6
+ bindir = $(PREFIX)/bin
7
+ T=../test_suite
8
+
9
+ all: hamzaNorm.pl
10
+
11
+ hamzaNorm.pl:
12
+ chmod +x hamzaNorm.pl
13
+
14
+ setTests:
15
+ cat $(T)/test.arb2004.txt | ./hamzaNorm.pl - $(T)/test.arb2004.hamzaNorm.txt
16
+ cat $(T)/test.arb2004.txt.stm | sed 's/<O>//' | ./hamzaNorm.pl -i stm - $(T)/test.arb2004.txt.stm.hamza
17
+ cat $(T)/test.arb2004.txt.ctm | ./hamzaNorm.pl -i ctm - - | sed 's/<O>//' > $(T)/test.arb2004.txt.ctm.hamza
18
+
19
+ check: all
20
+ @echo "Testing hamzaNorm.pl"
21
+ cat $(T)/test.arb2004.txt | ./hamzaNorm.pl -- - - | diff - $(T)/test.arb2004.hamzaNorm.txt
22
+ cat $(T)/test.arb2004.txt.stm | sed 's/<O>//' | ./hamzaNorm.pl -i stm -- - - | diff - $(T)/test.arb2004.txt.stm.hamza
23
+ cat $(T)/test.arb2004.txt.stm | ./hamzaNorm.pl -i stm -- - - | sed 's/<O>//' | diff - $(T)/test.arb2004.txt.stm.hamza
24
+ cat $(T)/test.arb2004.txt.ctm | ./hamzaNorm.pl -i ctm -- - - | sed 's/<O>//' | diff - $(T)/test.arb2004.txt.ctm.hamza
25
+ @echo " hamzaNorm.pl tests successfully completed"
26
+
27
+ install: all
28
+ cp hamzaNorm.pl $(DESTDIR)$(bindir)
29
+
30
+ clean:
31
+
32
+ distclean: clean
33
+ $(RM) -r *~ makefile
SCTK/src/hamzaNorm/makefile.in ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # **********************************************************
2
+ # Makefile for rfilter1 Directory
3
+ # **********************************************************
4
+ SHELL = /bin/sh
5
+ PREFIX=
6
+ bindir = $(PREFIX)/bin
7
+ T=../test_suite
8
+
9
+ all: hamzaNorm.pl
10
+
11
+ hamzaNorm.pl:
12
+ chmod +x hamzaNorm.pl
13
+
14
+ setTests:
15
+ cat $(T)/test.arb2004.txt | ./hamzaNorm.pl - $(T)/test.arb2004.hamzaNorm.txt
16
+ cat $(T)/test.arb2004.txt.stm | sed 's/<O>//' | ./hamzaNorm.pl -i stm - $(T)/test.arb2004.txt.stm.hamza
17
+ cat $(T)/test.arb2004.txt.ctm | ./hamzaNorm.pl -i ctm - - | sed 's/<O>//' > $(T)/test.arb2004.txt.ctm.hamza
18
+
19
+ check: all
20
+ @echo "Testing hamzaNorm.pl"
21
+ cat $(T)/test.arb2004.txt | ./hamzaNorm.pl -- - - | diff - $(T)/test.arb2004.hamzaNorm.txt
22
+ cat $(T)/test.arb2004.txt.stm | sed 's/<O>//' | ./hamzaNorm.pl -i stm -- - - | diff - $(T)/test.arb2004.txt.stm.hamza
23
+ cat $(T)/test.arb2004.txt.stm | ./hamzaNorm.pl -i stm -- - - | sed 's/<O>//' | diff - $(T)/test.arb2004.txt.stm.hamza
24
+ cat $(T)/test.arb2004.txt.ctm | ./hamzaNorm.pl -i ctm -- - - | sed 's/<O>//' | diff - $(T)/test.arb2004.txt.ctm.hamza
25
+ @echo " hamzaNorm.pl tests successfully completed"
26
+
27
+ install: all
28
+ cp hamzaNorm.pl $(DESTDIR)$(bindir)
29
+
30
+ clean:
31
+
32
+ distclean: clean
33
+ $(RM) -r *~ makefile
SCTK/src/rttmValidator/makefile ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ SHELL = /bin/sh
2
+ PREFIX=/home/userube/mozilla/zz__temp_5_rover/SCTK
3
+ bindir = $(PREFIX)/bin
4
+
5
+ all: rttmValidator.pl
6
+
7
+ rttmValidator.pl:
8
+ chmod +x rttmValidator.pl
9
+
10
+ check: all
11
+ (cd test_suite; $(SHELL) RunTest.sh ../rttmValidator.pl)
12
+
13
+ install: all
14
+ cp rttmValidator.pl $(DESTDIR)$(bindir)
15
+
16
+ clean:
17
+
18
+ distclean: clean
19
+ $(RM) -r *~ makefile
SCTK/src/rttmValidator/makefile.in ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ SHELL = /bin/sh
2
+ PREFIX=
3
+ bindir = $(PREFIX)/bin
4
+
5
+ all: rttmValidator.pl
6
+
7
+ rttmValidator.pl:
8
+ chmod +x rttmValidator.pl
9
+
10
+ check: all
11
+ (cd test_suite; $(SHELL) RunTest.sh ../rttmValidator.pl)
12
+
13
+ install: all
14
+ cp rttmValidator.pl $(DESTDIR)$(bindir)
15
+
16
+ clean:
17
+
18
+ distclean: clean
19
+ $(RM) -r *~ makefile
SCTK/src/rttmValidator/rttmValidator.pl ADDED
@@ -0,0 +1,917 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env perl
2
+
3
+ # RTTMVALIDATOR
4
+ # Author: Jon Fiscus, Jerome Ajot
5
+ #
6
+ # This software was developed at the National Institute of Standards and Technology by
7
+ # employees of the Federal Government in the course of their official duties. Pursuant
8
+ # to title 17 Section 105 of the United States Code this software is not subject to
9
+ # copyright protection and is in the public domain. RTTMVALIDATOR is an experimental system.
10
+ # NIST assumes no responsibility whatsoever for its use by other parties, and makes no
11
+ # guarantees, expressed or implied, about its quality, reliability, or any other
12
+ # characteristic. We would appreciate acknowledgement if the software is used.
13
+ #
14
+ # THIS SOFTWARE IS PROVIDED "AS IS." With regard to this software, NIST MAKES NO EXPRESS
15
+ # OR IMPLIED WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING MERCHANTABILITY,
16
+ # OR FITNESS FOR A PARTICULAR PURPOSE.
17
+
18
+ use warnings;
19
+ use strict;
20
+ use Getopt::Std;
21
+ use Data::Dumper;
22
+
23
+ my $debug = 0;
24
+
25
+ my $VERSION = "v13";
26
+
27
+ my $USAGE = "\n\n$0 [-useh] -i <RTTM file>\n\n".
28
+ "Version: $VERSION\n".
29
+ "Description: This Perl program (version $VERSION) validates a given RTTM file.\n".
30
+ "\tNote that the program will exit after it finds all the syntax errors or\n".
31
+ "\twhen it finds the first logic error.\n".
32
+ "Options:\n".
33
+ " -u : disable check that ensures all LEXEMEs belong to some SU object\n".
34
+ " -s : disable check that ensures all LEXEMEs belong to some SPEAKER object\n".
35
+ " -p : disable check that ensures all speakers defined in SPKR-INFO object\n".
36
+ " -e : disable check that ensure there is an IP for each EDIT and each FILLER object\n".
37
+ " -f : disable check that ensures the file columc matches the filename\n".
38
+ " -S : allow SCTK enhancements to allow multiple itme notations in LEXEME tags\n".
39
+ " -h : print this help message\n".
40
+ "Input:\n".
41
+ " -i <RTTM file>: an RTTM file\n\n";
42
+
43
+ #my $NUM_FIELDS = 9; # count from 1
44
+ #number of fields can be 9 or 10 (with the SLAT)
45
+
46
+ my $ROUNDING_THRESHOLD = 0.000999999;
47
+
48
+ my $checkFileName = 1; ### Check the filename against the file column
49
+
50
+ my %SORT_ORDER = ("NOSCORE" => 0,
51
+ "NO_RT_METADATA" => 1,
52
+ "SEGMENT" => 2,
53
+ "SPEAKER" => 3,
54
+ "SU" => 4,
55
+ "A/P" => 5,
56
+ "CB" => 6,
57
+ "IP" => 7,
58
+ "EDIT" => 8,
59
+ "FILLER" => 9,
60
+ "NON-SPEECH" => 10,
61
+ "NON-LEX" => 11,
62
+ "LEXEME" => 12,
63
+ "SPKR-INFO" => 13);
64
+
65
+ ########################################################
66
+ # Main
67
+ #
68
+ ########################################################
69
+ {
70
+ my ($date, $time) = date_time_stamp();
71
+ my $commandline = join(" ", @ARGV);
72
+
73
+ use vars qw ($opt_i $opt_u $opt_s $opt_e $opt_h $opt_f $opt_t $opt_p $opt_S);
74
+ getopts('i:usevhftpS');
75
+ die ("$USAGE") if ($opt_h) || (! $opt_i);
76
+
77
+ my @mde_types = ();
78
+ push (@mde_types, "SU") if ! $opt_u;
79
+ push (@mde_types, "SPEAKER") if ! $opt_s;
80
+ push (@mde_types, "EDIT") if ! $opt_e;
81
+ $checkFileName = ! $opt_f if $opt_f;
82
+ my $allowSCTKExtensions = 1 if $opt_S;
83
+
84
+ if (! $opt_t)
85
+ {
86
+ print "$0 (version $VERSION) run on $date at $time\n";
87
+ print "command line: ", $0, " (version ", $VERSION, ") ", $commandline, "\n";
88
+ }
89
+
90
+ my (%rttm_data, $data_domain);
91
+ get_rttm_data(\%rttm_data, \$data_domain, $opt_i, $allowSCTKExtensions);
92
+
93
+ # debug
94
+ #
95
+ my $count;
96
+ if ($debug) {
97
+ # print Dumper(%rttm_data);
98
+ foreach my $src (sort keys %rttm_data) {
99
+ foreach my $chnl (sort keys %{$rttm_data{$src}}) {
100
+ foreach my $spkr (sort keys %{$rttm_data{$src}{$chnl}}) {
101
+ foreach my $type (sort keys %{$rttm_data{$src}{$chnl}{$spkr}}) {
102
+ $count = 0;
103
+ foreach my $obj (@{$rttm_data{$src}{$chnl}{$spkr}{$type}}) {
104
+ print "[$src $chnl $spkr $type $count]\t$obj->{TYPE}\t$obj->{SRC}\t$obj->{CHNL}\t$obj->{TBEG}\t$obj->{TDUR}\t$obj->{ORTHO}\t$obj->{STYPE}\t$obj->{SPKR}\t$obj->{CONF}\n";
105
+ $count++;
106
+ }
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
112
+
113
+ if (check_syntax_errors(\%rttm_data, $data_domain, $opt_i, $allowSCTKExtensions) &&
114
+ check_logic_errors(\%rttm_data, \@mde_types)){
115
+ exit 0;
116
+ }
117
+ exit 1;
118
+ }
119
+
120
+ ########################################################
121
+ # Subroutines
122
+ #
123
+ ########################################################
124
+ sub get_rttm_data {
125
+
126
+ # read the RTTM file
127
+ #
128
+ my ($data, $domain, $file) = @_;
129
+
130
+ my (@fields, $obj);
131
+
132
+ my $line_num = 0;
133
+
134
+ ${$domain} = "";
135
+
136
+ open DATA, "$file" or die ("ERROR: Unable to open file $file\n");
137
+ while (<DATA>) {
138
+ $line_num++;
139
+ chomp;
140
+ if (/^\s*;;\s*EXP-ID:\s*(.*)/) {
141
+ my $exp_id = $1;
142
+ if ($exp_id =~ /bnews/i) {
143
+ ${$domain} = "bn";
144
+ } elsif ($exp_id =~ /cts/i) {
145
+ ${$domain} = "cts";
146
+ }
147
+ } elsif (! /^\s*;;/ && ! /^\s*$/) {
148
+ @fields = split;
149
+ undef $obj;
150
+ $obj->{FIELD_COUNT} = scalar (@fields);
151
+ $obj->{LOC} = "line $line_num";
152
+ $obj->{TYPE} = shift @fields;
153
+ $obj->{SRC} = shift @fields;
154
+ $obj->{CHNL} = shift @fields;
155
+ $obj->{TBEG} = shift @fields;
156
+ $obj->{TDUR} = shift @fields;
157
+ $obj->{ORTHO} = shift @fields;
158
+ $obj->{STYPE} = shift @fields;
159
+ $obj->{SPKR} = shift @fields;
160
+ $obj->{CONF} = shift @fields;
161
+ $obj->{SLAT} = shift @fields;
162
+ push (@{$data->{$obj->{SRC}}{$obj->{CHNL}}{$obj->{SPKR}}{$obj->{TYPE}}}, $obj);
163
+ }
164
+ }
165
+ close DATA;
166
+ }
167
+
168
+ sub check_syntax_errors {
169
+ # check for syntax errors such as missing fields,
170
+ # invalid field values, etc.
171
+ #
172
+ my ($data, $domain, $file, $allowSCTKExtensions) = @_;
173
+
174
+ my $pass = 1;
175
+
176
+ $file =~ s/\.[^\.]*$//;
177
+ $file =~ s/.*\///;
178
+
179
+ foreach my $src (sort keys %{$data}) {
180
+ foreach my $chnl (sort keys %{$data->{$src}}) {
181
+ foreach my $spkr (sort keys %{$data->{$src}{$chnl}}) {
182
+ foreach my $type (sort keys %{$data->{$src}{$chnl}{$spkr}}) {
183
+ foreach my $obj (@{$data->{$src}{$chnl}{$spkr}{$type}}) {
184
+ # make sure that we have the correct number of fields
185
+ #
186
+ # if ($obj->{FIELD_COUNT} != $NUM_FIELDS) {
187
+ if( ($obj->{FIELD_COUNT} != 9) && ($obj->{FIELD_COUNT} != 10) ){
188
+ print "ERROR: This record has $obj->{FIELD_COUNT} fields instead of the required 9 or 10 fields; see $obj->{LOC}\n";
189
+ $pass = 0;
190
+ }
191
+
192
+ # for the following checks to work, all the fields must be defined
193
+ #
194
+ if (defined ($obj->{TYPE}) && defined ($obj->{SRC}) &&
195
+ defined ($obj->{CHNL}) && defined ($obj->{TBEG}) &&
196
+ defined ($obj->{TDUR}) && defined ($obj->{ORTHO}) &&
197
+ defined ($obj->{STYPE}) && defined ($obj->{SPKR}) &&
198
+ defined ($obj->{CONF})) {
199
+
200
+ # make sure the type field is a valid RTTM type
201
+ #
202
+ if ($obj->{TYPE} !~ /^(SEGMENT|NOSCORE|NO_RT_METADATA|LEXEME|NON-LEX|NON-SPEECH|FILLER|EDIT|SU|IP|CB|A\/P|SPEAKER|SPKR-INFO)$/i) {
203
+ print "ERROR: Invalid RTTM type '$obj->{TYPE}'; see field (0) in $obj->{LOC}\n";
204
+ $pass = 0;
205
+ }
206
+
207
+ # make sure the source field matches the base filename.
208
+ # This won't work if people concat all the files into one.
209
+ # Make it a warning instead
210
+ #
211
+ if ($checkFileName && $obj->{SRC} !~ /^$file$/i) {
212
+ print "WARNING: Source field '$obj->{SRC}' doesn't match the input file's base filename '$file'; see field (2) in $obj->{LOC}\n";
213
+ }
214
+
215
+ # make sure the channel ID has a value of 1 or 2 but 1 for BN data
216
+ #
217
+ if ($obj->{CHNL} !~ /^(1|2)$/) {
218
+ print "ERROR: Invalid channel ID; see field (3) in $obj->{LOC}\n";
219
+ $pass = 0;
220
+ } elsif ($domain =~ /bn/i && $obj->{CHNL} != 1) {
221
+ print "ERROR: Expected channel ID to be 1 for BN data; see field (3) in $obj->{LOC}\n";
222
+ $pass = 0;
223
+ }
224
+
225
+ # make sure that if it's a SPKR-INFO the start time is <NA>
226
+ # else the start time must be a number and is non-negative
227
+ #
228
+ if ($obj->{TYPE} =~ /SPKR-INFO/i) {
229
+ if ($obj->{TBEG} !~ /<NA>/i) {
230
+ print "ERROR: $obj->{TYPE} should not have any start time; see field (4) in $obj->{LOC}\n";
231
+ $pass = 0;
232
+ }
233
+ } else {
234
+ if ($obj->{TBEG} !~ /^(\-{0,1}\d+\.?\d*|\-{0,1}\.\d+)\**$/) {
235
+ print "ERROR: Expected start time to be a number; see field (4) in $obj->{LOC}\n";
236
+ $pass = 0;
237
+ } else {
238
+ my $tbeg = $obj->{TBEG};
239
+ $tbeg =~ s/\*//;
240
+ if ($tbeg < 0) {
241
+ print "ERROR: Negative start time; see field (4) in $obj->{LOC}\n";
242
+ $pass = 0;
243
+ }
244
+ }
245
+ }
246
+
247
+ # make sure that if it's a SPKR-INFO, an IP, or a CB the duration is <NA>
248
+ # else the duration must be a number and is non-negative
249
+ #
250
+ if ($obj->{TYPE} =~ /(SPKR-INFO|IP|CB)/i) {
251
+ if ($obj->{TDUR} !~ /^<NA>$/i) {
252
+ print "ERROR: $obj->{TYPE} should not have any duration; see field (5) in $obj->{LOC}\n";
253
+ $pass = 0;
254
+ }
255
+ } else {
256
+ if ($obj->{TDUR} !~ /^(\-{0,1}\d+\.?\d*|\-{0,1}\.\d+)\**$/) {
257
+ print "ERROR: Expected duration to be a number; see field (5) in $obj->{LOC}\n";
258
+ $pass = 0;
259
+ } else {
260
+ my $tdur = $obj->{TDUR};
261
+ $tdur =~ s/\*//;
262
+ if ($tdur < 0) {
263
+ print "ERROR: Negative duration; see field (5) in $obj->{LOC}\n";
264
+ $pass = 0;
265
+ }
266
+ }
267
+ }
268
+
269
+ # make sure that if it's not a LEXEME or a NON-LEX it doesn't have any orthography
270
+ #
271
+ if ($obj->{TYPE} =~ /(SEGMENT|NOSCORE|NO_RT_METADATA|NON-SPEECH|FILLER|EDIT|SU|IP|CB|A\/P|SPEAKER|SPKR-INFO)/i) {
272
+ if ($obj->{ORTHO} !~ /^<NA>$/i) {
273
+ print "ERROR: Value for the orthography field for $obj->{TYPE} should be <NA>; see field (6) in $obj->{LOC}\n";
274
+ $pass = 0;
275
+ }
276
+ }
277
+
278
+ # make sure the subtype for various type is valid
279
+ #
280
+ if ($obj->{TYPE} =~ /SEGMENT/i) {
281
+ if ($obj->{STYPE} !~ /^(eval|<NA>)$/i) {
282
+ print "ERROR: Invalid $obj->{TYPE} subtype; see field (7) in $obj->{LOC}\n";
283
+ $pass = 0;
284
+ }
285
+ } elsif ($obj->{TYPE} =~ /(NOSCORE|NO_RT_METADATA|SPEAKER)/i) {
286
+ if ($obj->{STYPE} !~ /^<NA>$/i) {
287
+ print "ERROR: Invalid $obj->{TYPE} subtype; see field (7) in $obj->{LOC}\n";
288
+ $pass = 0;
289
+ }
290
+ } elsif ($obj->{TYPE} =~ /A\/P/i) {
291
+ if ($obj->{STYPE} !~ /^<NA>$/i) {
292
+ print "ERROR: Invalid $obj->{TYPE} subtype; see field (7) in $obj->{LOC}\n";
293
+ $pass = 0;
294
+ }
295
+ } elsif ($obj->{TYPE} =~ /LEXEME/i) {
296
+ if ($obj->{STYPE} !~ /^(lex|fp|frag|un-lex|for-lex|alpha|acronym|interjection|propernoun|other)$/i) {
297
+ print "ERROR: Invalid $obj->{TYPE} subtype; see field (7) in $obj->{LOC}\n";
298
+ $pass = 0;
299
+ }
300
+ if ($obj->{STYPE} =~ /alpha/i && $obj->{ORTHO} !~ /^([A-Z]\.|[A-Z]\.\'*s|[\x80-\xff]{2}\.|<NA>)$/i) {
301
+ print "ERROR: Invalid orthography for alpha $obj->{TYPE}; see field (6) '$obj->{ORTHO}' in $obj->{LOC}\n";
302
+ $pass = 0;
303
+ }
304
+ my $ww = '[\[\]A-Z\.\-\'\x80-\xff]+';
305
+ if (! $allowSCTKExtensions){
306
+ if ($obj->{ORTHO} !~ /^(${ww}|<NA>|%?[A-Z\.\x80-\xff]+-?)$/i) {
307
+ print "WARNING: Invalid orthography for $obj->{TYPE}; see field (6) '$obj->{ORTHO}' in $obj->{LOC}\n";
308
+ }
309
+ } else {
310
+ ### Destructively handle recursive alternations
311
+ my $_t = $obj->{ORTHO};
312
+ my $altExp = "\\{((_${ww})+_\\/)*(_${ww})+_\\}";
313
+ while ($_t =~ s/_${altExp}_/_/g){ ; }
314
+ if ($_t !~ /^(${ww}|(${ww}_)*$ww|$altExp|<NA>|%?[A-Z\.\x80-\xff]+-?)$/i) {
315
+ print "WARNING: Invalid orthography with SCTK Extensions for $obj->{TYPE}; see field (6) '$obj->{ORTHO}' in $obj->{LOC}\n";
316
+ }
317
+ }
318
+ } elsif ($obj->{TYPE} =~ /NON-LEX/i) {
319
+ #### fix lipsmack!!!!
320
+ if ($obj->{STYPE} !~ /^(laugh|breath|lipsmack|cough|sneeze|other)$/i) {
321
+ print "ERROR: Invalid $obj->{TYPE} subtype $obj->{STYPE}; see field (7) in $obj->{LOC}\n";
322
+ $pass = 0;
323
+ }
324
+ } elsif ($obj->{TYPE} =~ /NON-SPEECH/i) {
325
+ if ($obj->{STYPE} !~ /^(noise|music|other)$/i) {
326
+ print "ERROR: Invalid $obj->{TYPE} subtype; see field (7) in $obj->{LOC}\n";
327
+ $pass = 0;
328
+ }
329
+ } elsif ($obj->{TYPE} =~ /FILLER/i) {
330
+ if ($obj->{STYPE} !~ /^(filled_pause|discourse_marker|explicit_editing_term|discourse_response|other)$/i) {
331
+ print "ERROR: Invalid $obj->{TYPE} subtype; see field (7) in $obj->{LOC}\n";
332
+ $pass = 0;
333
+ }
334
+ } elsif ($obj->{TYPE} =~ /EDIT/i) {
335
+ if ($obj->{STYPE} !~ /^(repetition|restart|revision|simple|complex|other)$/i) {
336
+ print "ERROR: Invalid $obj->{TYPE} subtype; see field (7) in $obj->{LOC}\n";
337
+ $pass = 0;
338
+ }
339
+ } elsif ($obj->{TYPE} =~ /SU/i) {
340
+ if ($obj->{STYPE} !~ /^(statement|question|incomplete|backchannel|unannotated|discourse_response|other)$/i) {
341
+ print "ERROR: Invalid $obj->{TYPE} subtype; see field (7) in $obj->{LOC}\n";
342
+ $pass = 0;
343
+ }
344
+ } elsif ($obj->{TYPE} =~ /IP/i) {
345
+ if ($obj->{STYPE} !~ /^(edit|filler|edit\&filler|other)$/i) {
346
+ print "ERROR: Invalid $obj->{TYPE} subtype; see field (7) in $obj->{LOC}\n";
347
+ $pass = 0;
348
+ }
349
+ } elsif ($obj->{TYPE} =~ /CB/i) {
350
+ if ($obj->{STYPE} !~ /^(coordinating|clausal|other)$/i) {
351
+ print "ERROR: Invalid $obj->{TYPE} subtype; see field (7) in $obj->{LOC}\n";
352
+ $pass = 0;
353
+ }
354
+ } elsif ($obj->{TYPE} =~ /SPKR-INFO/i) {
355
+ if ($obj->{STYPE} !~ /^(adult_male|adult_female|child|unknown)$/) {
356
+ print "ERROR: Invalid $obj->{TYPE} subtype; see field (7) in $obj->{LOC}\n";
357
+ $pass = 0;
358
+ }
359
+ }
360
+
361
+ # make sure that the confidence field is a number it's from 0-1 else it's <NA>
362
+ #
363
+ if ($obj->{CONF} !~ /<NA>/) {
364
+ if ($obj->{CONF} !~ /^(\-{0,1}\d+\.?\d*|\-{0,1}\.\d+)$/) {
365
+ print "ERROR: Expected confidence value to be a number or <NA>; see field (9) in $obj->{LOC}\n";
366
+ $pass = 0;
367
+ } elsif ($obj->{CONF} < 0 || $obj->{CONF} > 1) {
368
+ print "ERROR: Expected confidence value to be [0,1]; see field (9) in $obj->{LOC}\n";
369
+ $pass = 0;
370
+ }
371
+ }
372
+
373
+ # make sure that the speaker id field for certain types match the speaker id
374
+ # given in the SPKR-INFO object
375
+ #
376
+ if( ! $opt_p )
377
+ {
378
+ if ($type !~ /(SPKR-INFO|NOSCORE|NONSPEECH)/i && ! find_speaker($obj->{SPKR}, $data) ) {
379
+ print "ERROR: Speaker $obj->{SPKR} doesn't match any of the speaker IDs in SPKR-INFO objects; see $obj->{LOC}\n";
380
+ $pass = 0;
381
+ }
382
+ }
383
+ }
384
+ }
385
+ }
386
+ }
387
+ }
388
+ }
389
+ if (! $pass) {
390
+ print "Validation aborted\n";
391
+ }
392
+ return $pass;
393
+ }
394
+
395
+ sub check_logic_errors {
396
+ # check for logic errors such as overlapping words from the same speaker, etc.
397
+ #
398
+ my ($data, $mde_types) = @_;
399
+
400
+ # sort the data
401
+ #
402
+ foreach my $src (sort keys %{$data}) {
403
+ foreach my $chnl (sort keys %{$data->{$src}}) {
404
+ foreach my $spkr (sort keys %{$data->{$src}{$chnl}}) {
405
+ foreach my $type (sort keys %{$data->{$src}{$chnl}{$spkr}}) {
406
+ if ($type !~ /SPKR-INFO/i) {
407
+ @{$data->{$src}{$chnl}{$spkr}{$type}} =
408
+ sort {$a->{TBEG} <=> $b->{TBEG}} @{$data->{$src}{$chnl}{$spkr}{$type}};
409
+ }
410
+ }
411
+ }
412
+ }
413
+ }
414
+
415
+ if (check_metadata_overlap($data) &&
416
+ check_metadata_content($data) &&
417
+ check_partial_word_coverage($data) &&
418
+ check_noscore_overlap($data)) {
419
+ foreach my $type (@$mde_types) {
420
+ if ($type =~ /(SU|SPEAKER)/i) {
421
+ if (! ensure_word_covered_by_metadata_of_type($data, $type)) {
422
+ return 0;
423
+ }
424
+ }
425
+ if ($type =~ /(EDIT|FILLER)/i) {
426
+ if (! ensure_ip_existed_for_edit_and_filler($data)) {
427
+ return 0;
428
+ }
429
+ }
430
+ }
431
+ return 1;
432
+ } else {
433
+ return 0;
434
+ }
435
+ }
436
+
437
+ sub check_metadata_overlap {
438
+ # check if two metadata objects of the same type
439
+ # from the same speaker overlap
440
+ #
441
+ my ($data) = @_;
442
+
443
+ my $pass = 1;
444
+
445
+ foreach my $src (sort keys %{$data}) {
446
+ foreach my $chnl (sort keys %{$data->{$src}}) {
447
+ foreach my $spkr (sort keys %{$data->{$src}{$chnl}}) {
448
+ foreach my $type (sort keys %{$data->{$src}{$chnl}{$spkr}}) {
449
+ if ($type !~ /SPKR-INFO/i) {
450
+ my $prev_etime = 0;
451
+ foreach my $obj (@{$data->{$src}{$chnl}{$spkr}{$type}}) {
452
+ if (($prev_etime - $obj->{TBEG}) > $ROUNDING_THRESHOLD) {
453
+ print "ERROR: Speaker $spkr has ${type}s ending at $prev_etime and starting at $obj->{TBEG}; ${type}s overlap; see $obj->{LOC}\n";
454
+ $pass = 0;
455
+ }
456
+ if ($type =~ /(CB|IP)/i) {
457
+ $prev_etime = $obj->{TBEG};
458
+ } else {
459
+ $prev_etime = $obj->{TBEG} + $obj->{TDUR};
460
+ }
461
+ }
462
+ }
463
+ }
464
+ }
465
+ }
466
+ }
467
+ if (! $pass) {
468
+ print "Validation aborted\n";
469
+ }
470
+ return $pass;
471
+ }
472
+
473
+ sub check_metadata_content {
474
+ # check if a metadata object of type SU, EDIT, or FILLER contains any words.
475
+ # The words could be missing or simply didn't get transcribed
476
+ #
477
+ my ($data) = @_;
478
+
479
+ my $pass = 1;
480
+
481
+ foreach my $src (sort keys %{$data}) {
482
+ foreach my $chnl (sort keys %{$data->{$src}}) {
483
+ foreach my $spkr (sort keys %{$data->{$src}{$chnl}}) {
484
+ foreach my $type (sort keys %{$data->{$src}{$chnl}{$spkr}}) {
485
+ if ($type =~ /(SU|EDIT|FILLER)/i) {
486
+ foreach my $obj (@{$data->{$src}{$chnl}{$spkr}{$type}}) {
487
+ if (! find_word($data->{$src}{$chnl}{$spkr}{LEXEME}, $obj->{TBEG}, $obj->{TBEG} + $obj->{TDUR})) {
488
+ print "ERROR: $type at $obj->{TBEG} contains no words; see $obj->{LOC}\n";
489
+ $pass = 0;
490
+ }
491
+ }
492
+ }
493
+ }
494
+ }
495
+ }
496
+ }
497
+ if (! $pass) {
498
+ print "Validation aborted\n";
499
+ }
500
+ return $pass;
501
+ }
502
+
503
+ sub check_partial_word_coverage {
504
+ # check if a given word partially overlaps with
505
+ # any metadata object of type SU, EDIT, or FILLER
506
+ #
507
+ my ($data) = @_;
508
+
509
+ my $pass = 1;
510
+
511
+ foreach my $src (sort keys %{$data}) {
512
+ foreach my $chnl (sort keys %{$data->{$src}}) {
513
+ foreach my $spkr (sort keys %{$data->{$src}{$chnl}}) {
514
+ foreach my $type (sort keys %{$data->{$src}{$chnl}{$spkr}}) {
515
+ if ($type =~ /LEXEME/i) {
516
+ foreach my $obj (@{$data->{$src}{$chnl}{$spkr}{$type}}) {
517
+ foreach my $mde_type (sort keys %{$data->{$src}{$chnl}{$spkr}}) {
518
+ if ($mde_type =~ /(SU|EDIT|FILLER)/i) {
519
+ if (find_partial_coverage($data->{$src}{$chnl}{$spkr}{$mde_type}, $obj->{TBEG}, $obj->{TBEG} + $obj->{TDUR})) {
520
+ print "ERROR: Word at $obj->{TBEG} is partially covered by $mde_type object; see $obj->{LOC}\n";
521
+ $pass = 0;
522
+ }
523
+ }
524
+ }
525
+ }
526
+ }
527
+ }
528
+ }
529
+ }
530
+ }
531
+ if (! $pass) {
532
+ print "Validation aborted\n";
533
+ }
534
+ return $pass;
535
+ }
536
+
537
+ sub check_noscore_overlap {
538
+ # check if a metadata object of type
539
+ # SU, EDIT, FILLER, SPEAKER, LEXEME, NONLEX, NONSPEECH
540
+ # partially overlap with noscore regions
541
+ #
542
+ my ($data) = @_;
543
+
544
+ my $pass = 1;
545
+
546
+ foreach my $src (sort keys %{$data}) {
547
+ foreach my $chnl (sort keys %{$data->{$src}}) {
548
+ next if (! defined ($data->{$src}{$chnl}{"<NA>"}{NOSCORE}));
549
+ foreach my $spkr (sort keys %{$data->{$src}{$chnl}}) {
550
+ foreach my $type (sort keys %{$data->{$src}{$chnl}{$spkr}}) {
551
+ if ($type =~ /(SU|EDIT|FILLER|SPEAKER|LEXEME|NON-LEX|NON-SPEECH)/i) {
552
+ foreach my $obj (@{$data->{$src}{$chnl}{$spkr}{$type}}) {
553
+ if (find_partial_coverage($data->{$src}{$chnl}{"<NA>"}{NOSCORE}, $obj->{TBEG}, $obj->{TBEG} + $obj->{TDUR})) {
554
+ print "ERROR: Speaker $spkr has $type partially overlapping with NOSCORE tag at $obj->{TBEG}; see $obj->{LOC}\n";
555
+ $pass = 0;
556
+ }
557
+ }
558
+ }
559
+ }
560
+ }
561
+ }
562
+ }
563
+ if (! $pass) {
564
+ print "Validation aborted\n";
565
+ }
566
+ return $pass;
567
+ }
568
+
569
+ sub ensure_word_covered_by_metadata_of_type {
570
+ # make sure that all words belong to some metadata object of the given type.
571
+ #
572
+ my ($data, $mde_type) = @_;
573
+
574
+ my $pass = 1;
575
+
576
+ foreach my $src (sort keys %{$data}) {
577
+ foreach my $chnl (sort keys %{$data->{$src}}) {
578
+ foreach my $spkr (sort keys %{$data->{$src}{$chnl}}) {
579
+ foreach my $type (sort keys %{$data->{$src}{$chnl}{$spkr}}) {
580
+ if ($type =~ /LEXEME/i) {
581
+ foreach my $obj (@{$data->{$src}{$chnl}{$spkr}{$type}}) {
582
+ if (! find_type($data->{$src}{$chnl}{$spkr}{$mde_type}, $obj->{TBEG}, $obj->{TBEG} + $obj->{TDUR})) {
583
+ print "ERROR: Word at $obj->{TBEG} doesn't belong to any $mde_type object; see $obj->{LOC}\n";
584
+ $pass = 0;
585
+ }
586
+ }
587
+ }
588
+ }
589
+ }
590
+ }
591
+ }
592
+ if (! $pass) {
593
+ print "Validation aborted\n";
594
+ }
595
+ return $pass;
596
+ }
597
+
598
+ sub ensure_ip_existed_for_edit_and_filler {
599
+ # make sure that for each EDIT or FILLER there is
600
+ # a valid IP that follows or precedes it
601
+ #
602
+ my ($data) = @_;
603
+
604
+ my $pass = 1;
605
+
606
+ foreach my $src (sort keys %{$data}) {
607
+ foreach my $chnl (sort keys %{$data->{$src}}) {
608
+ foreach my $spkr (sort keys %{$data->{$src}{$chnl}}) {
609
+ if (exists($data->{$src}{$chnl}{$spkr}{SU})) {
610
+ my @sus = @{$data->{$src}{$chnl}{$spkr}{SU}};
611
+ for (my $i = 0; $i < @sus; $i++) {
612
+ # print "SU $sus[$i]->{TBEG}\n";
613
+ my @edits = ();
614
+ my @fillers = ();
615
+ my @ips = ();
616
+ if (exists($data->{$src}{$chnl}{$spkr}{EDIT})) {
617
+ @edits = extract_mde_of_type($sus[$i]->{TBEG},
618
+ $sus[$i]->{TBEG} + $sus[$i]->{TDUR},
619
+ $i,
620
+ "EDIT",
621
+ $data->{$src}{$chnl}{$spkr}{EDIT},
622
+ \@sus);
623
+ }
624
+ if (exists($data->{$src}{$chnl}{$spkr}{FILLER})) {
625
+ @fillers = extract_mde_of_type($sus[$i]->{TBEG},
626
+ $sus[$i]->{TBEG} + $sus[$i]->{TDUR},
627
+ $i,
628
+ "FILLER",
629
+ $data->{$src}{$chnl}{$spkr}{FILLER},
630
+ \@sus);
631
+ }
632
+ if (exists($data->{$src}{$chnl}{$spkr}{IP})) {
633
+ @ips = extract_mde_of_type($sus[$i]->{TBEG},
634
+ $sus[$i]->{TBEG} + $sus[$i]->{TDUR},
635
+ $i,
636
+ "IP",
637
+ $data->{$src}{$chnl}{$spkr}{IP},
638
+ \@sus);
639
+ }
640
+ # print "edits\n";
641
+ # print Dumper(@edits);
642
+ # print "fillers\n";
643
+ # print Dumper(@fillers);
644
+ # print "ips\n";
645
+ # print Dumper(@ips);
646
+
647
+ foreach my $obj (@edits) {
648
+ my ($status, $ip_stype, $ip_pos) = find_object($obj->[0], $obj->[1], \@ips);
649
+ if ($status == 1) {
650
+ # print "$status, edit_type=$obj->[1] ip_stype=$ip_stype $ip_pos\n";
651
+ if ($ip_stype =~ /^EDIT$/i) {
652
+ # print "case 1\n";
653
+ $obj->[4] = 1;
654
+ $ips[$ip_pos]->[4] = 1;
655
+ } elsif ($ip_stype =~ /^EDIT&FILLER$/i) {
656
+ foreach my $obj2 (@fillers) {
657
+ my ($status2, $filler_type, $filler_pos) = find_object($obj->[0], "FILLER", \@fillers);
658
+ if ($status2 == 1) {
659
+ # print "$status2, filler_type=FILLER filler_type=$filler_type $filler_pos\n";
660
+ # print "case 2\n";
661
+ $obj->[4] = 1;
662
+ $ips[$ip_pos]->[4] = 1;
663
+ $fillers[$filler_pos]->[4] = 1;
664
+ }
665
+ }
666
+ }
667
+ }
668
+ }
669
+
670
+ foreach my $obj (@fillers) {
671
+ my ($status, $ip_stype, $ip_pos) = find_object($obj->[0], $obj->[1], \@ips);
672
+ if ($status == 1) {
673
+ # print "$status, filler type=$obj->[1] ip stype=$ip_stype, $ip_pos\n";
674
+ # print "case 3\n";
675
+
676
+ if ($ip_stype =~ /^FILLER$/i) {
677
+ $obj->[4] = 1;
678
+ $ips[$ip_pos]->[4] = 1;
679
+ }
680
+ }
681
+ }
682
+
683
+ foreach my $obj (@edits) {
684
+ if ($obj->[4] == 0) {
685
+ print "ERROR: EDIT at $obj->[2] doesn't have a matching IP; see $obj->[3]\n";
686
+ $pass = 0;
687
+ }
688
+ }
689
+ foreach my $obj (@fillers) {
690
+ if ($obj->[4] == 0) {
691
+ print "ERROR: FILLER at $obj->[2] doesn't have a matching IP; see $obj->[3]\n";
692
+ $pass = 0;
693
+ }
694
+ }
695
+ foreach my $obj (@ips) {
696
+ if ($obj->[4] == 0) {
697
+ print "ERROR: IP at $obj->[2] doesn't have a matching EDIT and/or FILLER; see line $obj->[3]\n";
698
+ $pass = 0;
699
+ }
700
+ }
701
+ }
702
+ }
703
+ }
704
+ }
705
+ }
706
+ if (! $pass) {
707
+ print "Validation aborted\n";
708
+ }
709
+ return $pass;
710
+ }
711
+
712
+ sub find_object {
713
+ my ($time, $type, $data1) = @_;
714
+ # print "find object ------------\n";
715
+ # print " $time $type\n";
716
+ for (my $i=0; $i < @$data1; $i++) {
717
+ # print " ${$data1}[$i]->[0]\n";
718
+ if (abs(${$data1}[$i]->[0] - $time) < $ROUNDING_THRESHOLD &&
719
+ ${$data1}[$i]->[4] != 1) {
720
+ # print " found\n";
721
+ return (1, ${$data1}[$i]->[1], $i);
722
+ }
723
+ }
724
+ return (0, undef, undef);
725
+ }
726
+
727
+ sub find_partial_coverage {
728
+ # determine if a given object (indicated by its start and end times)
729
+ # partially overlap with any object of the given type
730
+ #
731
+ my ($data, $start, $end) = @_;
732
+
733
+ my $obj;
734
+
735
+ foreach $obj (@{$data}) {
736
+ my $curr_beg = $obj->{TBEG};
737
+ my $curr_end = $obj->{TBEG} + $obj->{TDUR};
738
+
739
+ # case 1 #########
740
+ # ####
741
+ #
742
+ # case 2 ########
743
+ # ####
744
+ #
745
+ # case 3 ########
746
+ # ####
747
+ #
748
+ # everything else is partially covered
749
+ #
750
+ if (less_than($end, $curr_beg) || equal_to($end, $curr_beg)) {
751
+ # case 1
752
+ next;
753
+ } elsif (greater_than($start, $curr_end) || equal_to($start, $curr_end)) {
754
+ # case 2
755
+ next;
756
+ } elsif ( ( greater_than($start, $curr_beg) || equal_to($start, $curr_beg) ) &&
757
+ ( less_than($end, $curr_end) || equal_to($end, $curr_end) ) ) {
758
+ # case 3
759
+ next;
760
+ } else {
761
+ # others
762
+ return 1;
763
+ }
764
+ }
765
+ return 0;
766
+ }
767
+
768
+ sub find_type {
769
+ # determine if a given word (indicated by its start and end times)
770
+ # belongs to any metadata object of the given type
771
+ #
772
+ my ($data, $token_start, $token_end) = @_;
773
+
774
+ foreach my $mde_obj (@{$data}) {
775
+ if ($token_start + $ROUNDING_THRESHOLD >= $mde_obj->{TBEG} &&
776
+ $token_end - $ROUNDING_THRESHOLD <= $mde_obj->{TBEG} + $mde_obj->{TDUR}) {
777
+ return 1;
778
+ }
779
+ }
780
+ return 0;
781
+ }
782
+
783
+ sub find_word {
784
+ # determine if a given metadata object (indicated by its start and end times)
785
+ # contains any word
786
+ #
787
+ my ($data, $mde_obj_start, $mde_obj_end) = @_;
788
+
789
+ foreach my $token (@{$data}) {
790
+ if ($token->{TBEG} + $ROUNDING_THRESHOLD >= $mde_obj_start &&
791
+ $token->{TBEG} + $token->{TDUR} - $ROUNDING_THRESHOLD <= $mde_obj_end) {
792
+ return 1;
793
+ }
794
+ }
795
+ return 0;
796
+ }
797
+
798
+ sub find_ip {
799
+ # determine if an IP is at the time given
800
+ #
801
+ my ($data, $tbeg, $tend, $target) = @_;
802
+ if ($tbeg && $tend && $target) {
803
+ foreach my $ip (@{$data}) {
804
+ if ( $tbeg <= $ip->{TBEG} &&
805
+ $ip->{TBEG} <= $tend &&
806
+ abs($ip->{TBEG} - $target) < $ROUNDING_THRESHOLD ) {
807
+ return $ip;
808
+ }
809
+ }
810
+ }
811
+ return undef;
812
+ }
813
+
814
+ sub find_speaker {
815
+ # determine if a given speaker is in the data
816
+ #
817
+ my ($src_spkr, $data) = @_;
818
+
819
+ my ($curr_spkr);
820
+ foreach my $src (sort keys %{$data}) {
821
+ foreach my $chnl (sort keys %{$data->{$src}}) {
822
+ foreach my $spkr (sort keys %{$data->{$src}{$chnl}}) {
823
+ foreach my $obj (@{$data->{$src}{$chnl}{$spkr}{'SPKR-INFO'}}) {
824
+ $curr_spkr = $obj->{SPKR};
825
+ if ($src_spkr =~ /^$curr_spkr$/i) {
826
+ return 1;
827
+ }
828
+ }
829
+ }
830
+ }
831
+ }
832
+ return 0;
833
+ }
834
+
835
+ sub extract_mde_of_type {
836
+ # for a given SU (indicated by its begin and end times)
837
+ # return all the MDE objects of the given type in that SU
838
+ #
839
+ my ($su_tbeg, $su_tend, $su_pos, $mde_type, $data, $sus) = @_;
840
+ my @ip_time = ();
841
+ if ($mde_type =~ /EDIT/i) {
842
+ foreach my $obj (@$data) {
843
+ if ( (greater_than($obj->{TBEG}, $su_tbeg) || equal_to ($obj->{TBEG}, $su_tbeg)) &&
844
+ (less_than($obj->{TBEG} + $obj->{TDUR}, $su_tend) || equal_to ($obj->{TBEG} + $obj->{TDUR}, $su_tend)) ) {
845
+ push (@ip_time, [ $obj->{TBEG} + $obj->{TDUR}, uc($obj->{TYPE}), $obj->{TBEG}, $obj->{LOC}, 0 ]);
846
+ }
847
+ }
848
+ } elsif ($mde_type =~ /FILLER/i) {
849
+ foreach my $obj (@$data) {
850
+ if ( (greater_than($obj->{TBEG}, $su_tbeg) || equal_to ($obj->{TBEG}, $su_tbeg)) &&
851
+ (less_than($obj->{TBEG} + $obj->{TDUR}, $su_tend) || equal_to ($obj->{TBEG} + $obj->{TDUR}, $su_tend)) ) {
852
+ push (@ip_time, [ $obj->{TBEG}, uc($obj->{TYPE}), $obj->{TBEG}, $obj->{LOC}, 0 ]);
853
+ }
854
+ }
855
+ } elsif ($mde_type =~ /IP/i) {
856
+ foreach my $obj (@$data) {
857
+ if ( (greater_than($obj->{TBEG}, $su_tbeg) && less_than($obj->{TBEG}, $su_tend) ) ||
858
+ equal_to($obj->{TBEG}, $su_tbeg) ) {
859
+ push (@ip_time, [ $obj->{TBEG}, uc($obj->{STYPE}), $obj->{TBEG}, $obj->{LOC}, 0 ]);
860
+ } elsif ( equal_to($obj->{TBEG}, $su_tend) ) {
861
+ if ($su_pos + 1 <= scalar($sus)) {
862
+ if ( equal_to($su_tend, $sus->[$su_pos + 1]->{TBEG}) &&
863
+ $obj->{STYPE} !~ /filler/i ) {
864
+ push (@ip_time, [ $obj->{TBEG}, uc($obj->{STYPE}), $obj->{TBEG}, $obj->{LOC}, 0 ]);
865
+ }
866
+ }
867
+ }
868
+ }
869
+ }
870
+ return @ip_time;
871
+ }
872
+
873
+ sub sort_data {
874
+ return ($a->{TBEG} < $b->{TBEG} - $ROUNDING_THRESHOLD ? -1 :
875
+ ($a->{TBEG} > $b->{TBEG} + $ROUNDING_THRESHOLD ? 1 :
876
+ $SORT_ORDER{$a->{TYPE}} <=> $SORT_ORDER{$b->{TYPE}}));
877
+ }
878
+
879
+ sub less_than {
880
+ # if a < b return 1
881
+ #
882
+ my ($a, $b) = @_;
883
+ if ($a + $ROUNDING_THRESHOLD < $b) {
884
+ return 1;
885
+ }
886
+ return 0;
887
+ }
888
+
889
+ sub greater_than {
890
+ # if a > b return 1
891
+ #
892
+ my ($a, $b) = @_;
893
+ if ($a > $b + $ROUNDING_THRESHOLD) {
894
+ return 1;
895
+ }
896
+ return 0;
897
+ }
898
+
899
+ sub equal_to {
900
+ # if a == b return 1
901
+ #
902
+ my ($a, $b) = @_;
903
+ if ( abs($a - $b) < $ROUNDING_THRESHOLD) {
904
+ return 1;
905
+ }
906
+ return 0;
907
+ }
908
+
909
+ sub date_time_stamp {
910
+ my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime();
911
+ my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
912
+ my ($date, $time);
913
+
914
+ $time = sprintf "%2.2d:%2.2d:%2.2d", $hour, $min, $sec;
915
+ $date = sprintf "%4.4s %3.3s %s", 1900+$year, $months[$mon], $mday;
916
+ return ($date, $time);
917
+ }
SCTK/src/sclite/addarc1.o ADDED
Binary file (3.22 kB). View file
 
SCTK/src/sclite/alex.h ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* File: alex.h */
2
+
3
+ typedef struct AUTO_LEX_struct{
4
+ int max, /* total possible tokens */
5
+ num; /* current number of stored tokens */
6
+ TEXT **str; /* pointer to the list of texts */
7
+ int *field_a; /* pointer to a list if intergers */
8
+ /* used for any purpose what-so-ever, */
9
+ /* Intitializd to ZERO */
10
+ int *field_b; /* Same usage as field_a . . . */
11
+ double *field_c; /* Same usage as field_a . . . */
12
+ int *sort; /* Sorted list of the texts */
13
+ } AUTO_LEX;
14
+
15
+ void AUTO_LEX_init(AUTO_LEX *alex, int size);
16
+ void AUTO_LEX_free(AUTO_LEX *alex);
17
+ int AUTO_LEX_insert(AUTO_LEX *alex, TEXT *new);
18
+ void AUTO_LEX_dump(AUTO_LEX *alex, FILE *fp);
19
+ TEXT *AUTO_LEX_get(AUTO_LEX *alex, int ind);
20
+ void AUTO_LEX_printout(AUTO_LEX *alex, FILE *fp, char *title, int threshhold);
21
+ double AUTO_LEX_get_c(AUTO_LEX *alex, int ind);
22
+ int AUTO_LEX_find(AUTO_LEX *alex, TEXT *str);
23
+
SCTK/src/sclite/align.c ADDED
@@ -0,0 +1,1443 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <unistd.h>
2
+ #include "sctk.h"
3
+
4
+
5
+ void remove_id(TEXT *utt, TEXT **id, int *len);
6
+ int extract_speaker(TEXT *hyp_id, TEXT *sname, enum id_types id);
7
+ void load_refs(SCORES *sc, char *hyp_file, char *ref_file, TEXT ***rset, TEXT ***refid, int *refcnt, int case_sense);
8
+ void free_refs(TEXT ***rset, TEXT ***ref_id, int refcnt);
9
+ void convert_text_to_word_list(char *file, char *words,int case_sense);
10
+ void expand_words_to_chars(ARC *arc, void *ptr);
11
+ void decode_opt_del(ARC *arc, void *ptr);
12
+ void decode_fragment(ARC *arc, void *ptr);
13
+ void lookup_word_weight(ARC *arc, void *ptr);
14
+ void set_word_duration(ARC *arc, void *ptr);
15
+ void set_word_start(ARC *arc, void *ptr);
16
+ void set_word_conf(ARC *arc, void *ptr);
17
+ void set_word_opt_del(ARC *arc, void *ptr);
18
+
19
+
20
+ #define LOAD_BUFF_LEN 1000
21
+
22
+ void remove_id(TEXT *utt, TEXT **id, int *id_len){
23
+ TEXT *L_paren, *R_paren;
24
+
25
+ R_paren = TEXT_strrchr(utt,')');
26
+ L_paren = TEXT_strrchr(utt,'(');
27
+
28
+ **id = NULL_TEXT;
29
+
30
+ if (R_paren == NULL && L_paren == NULL)
31
+ return;
32
+
33
+ if (R_paren == NULL || L_paren == NULL){
34
+ fprintf(stderr,"Error: Unparsable utterance id %s\n",utt);
35
+ exit(1);
36
+ }
37
+
38
+ /* make sure there is enough space */
39
+ if (R_paren - L_paren + 1 + 1 > *id_len){
40
+ *id_len = R_paren - L_paren + 1 + 1 + 10;
41
+ free_singarr(*id,TEXT);
42
+ alloc_singZ((*id),*id_len,TEXT,'\0');
43
+ }
44
+ TEXT_strBcpy(*id,L_paren,R_paren - L_paren + 1);
45
+ *(*id + (R_paren - L_paren + 1)) = NULL_TEXT;
46
+ *L_paren = NULL_TEXT;
47
+ }
48
+
49
+ int extract_speaker(TEXT *id, TEXT *sname, enum id_types idt){
50
+ char *proc = "extract_speaker";
51
+ TEXT *p;
52
+ switch (idt){
53
+ case SP:
54
+ TEXT_strcpy(sname, id);
55
+ return(0);
56
+ case ATIS:
57
+ case WSJ:
58
+ TEXT_strBcpy(sname, id + 1, 3);
59
+ sname[3] = NULL_TEXT;
60
+ return(0);
61
+ case RM:
62
+ case SPUID:
63
+ case SWB:
64
+ if (((p = TEXT_strchr(id,'-')) == NULL) &&
65
+ ((p = TEXT_strchr(id,'_')) == NULL)){
66
+ fprintf(stderr,"Error: %s can't locate ",proc);
67
+ switch (idt){
68
+ case RM: fprintf(stderr,"%s id %s\n","RM",id); break;
69
+ case SPUID: fprintf(stderr,"%s id %s\n","SPU_ID",id); break;
70
+ case SWB: fprintf(stderr,"%s id %s\n","SWB",id); break;
71
+ case WSJ:
72
+ case ATIS:
73
+ default: fprintf(stderr,"*** internal error\n");
74
+ }
75
+ return(1);
76
+ }
77
+ TEXT_strBcpy(sname, id + 1, p - (id+1));
78
+ sname[p - (id+1)] = NULL_TEXT;
79
+ return(0);
80
+ default:
81
+ fprintf(stderr,"Error: %s unknown id type\n",proc);
82
+ return(1);
83
+ }
84
+ }
85
+
86
+ /* free the reference transcripts */
87
+ void free_refs(TEXT ***rset, TEXT ***ref_id, int refcnt){
88
+ free_2dimarr((*rset),refcnt,TEXT);
89
+ free_2dimarr((*ref_id),refcnt,TEXT);
90
+ }
91
+
92
+ void load_refs(SCORES *sc, char *hyp_file, char *ref_file, TEXT ***rset, TEXT ***refid, int *refcnt, int case_sense){
93
+ TEXT *in_buf, *id_buf;
94
+ int in_buf_len=LOAD_BUFF_LEN, id_buf_len=LOAD_BUFF_LEN;
95
+ FILE *fp;
96
+ TEXT **idset, **tidset, **refset, **refids;
97
+ int max_ids, num_ids, i, num_ref, failure=0;
98
+
99
+ max_ids = 3; num_ids = 0; num_ref = 0;
100
+ alloc_singZ(idset,max_ids,TEXT *,(TEXT *)0);
101
+ alloc_singZ(in_buf,in_buf_len,TEXT,'\0');
102
+ alloc_singZ(id_buf,id_buf_len,TEXT,'\0');
103
+
104
+ /* Pre-Read the entire hypothesis file */
105
+ if ((hyp_file == NULL) || (*hyp_file == '\0') ||
106
+ ((fp = fopen(hyp_file,"r")) == NULL)){
107
+ fprintf(stderr,"Can't open input hypothesis file %s\n",hyp_file);
108
+ exit(1);
109
+ }
110
+ while (!feof(fp)){
111
+ *in_buf = *(in_buf+1) = COMMENT_CHAR;
112
+ *(in_buf+2) = NULL_TEXT;
113
+ while (!feof(fp) && (parse_input_comment_line(sc,in_buf) ||
114
+ TEXT_is_comment_info(in_buf) ||
115
+ TEXT_is_empty(in_buf))){
116
+ if (TEXT_ensure_fgets(&in_buf,&in_buf_len,fp) == NULL)
117
+ *in_buf = NULL_TEXT;
118
+ }
119
+ if (!feof(fp)){
120
+ if (!case_sense)
121
+ TEXT_str_case_change_with_mem_expand(&in_buf, &in_buf_len, 1);
122
+ remove_id(in_buf,&id_buf,&id_buf_len);
123
+ if (num_ids + 1 >= max_ids) {
124
+ /* expanding the array */
125
+ alloc_singZ(tidset,max_ids*2,TEXT *, (TEXT *)0);
126
+ memcpy(tidset,idset,sizeof(TEXT *) * num_ids);
127
+ free_singarr(idset,TEXT *);
128
+ idset = tidset;
129
+ max_ids *= 2;
130
+ }
131
+ idset[num_ids++] = TEXT_strdup(id_buf);
132
+ }
133
+ }
134
+ fclose(fp);
135
+
136
+ /* sort the id's in-place */
137
+ qsort((void *)idset,num_ids,sizeof(TEXT *),qsort_TEXT_strcmp);
138
+
139
+ /* space for the reference transcripts allocate */
140
+ alloc_singZ(refset,num_ids,TEXT *,(TEXT *)0);
141
+
142
+ /* Read the reference file, saving the needed texts */
143
+ if ((ref_file == NULL) || (*ref_file == '\0') ||
144
+ ((fp = fopen(ref_file,"r")) == NULL)){
145
+ fprintf(stderr,"Can't open input Reference file %s\n",ref_file);
146
+ exit(1);
147
+ }
148
+ while (!feof(fp)){
149
+ TEXT **ind;
150
+ int rind;
151
+
152
+ *in_buf = *(in_buf+1) = COMMENT_CHAR;
153
+ *(in_buf+2) = NULL_TEXT;
154
+ while (!feof(fp) && (parse_input_comment_line(sc,in_buf) ||
155
+ TEXT_is_comment_info(in_buf) ||
156
+ TEXT_is_empty(in_buf))){
157
+ if (TEXT_ensure_fgets(&in_buf,&in_buf_len,fp) == NULL)
158
+ *in_buf = '\0';
159
+ }
160
+ if (feof(fp))
161
+ break;
162
+
163
+ if (!case_sense)
164
+ TEXT_str_case_change_with_mem_expand(&in_buf, &in_buf_len, 1);
165
+
166
+ remove_id(in_buf,&id_buf,&id_buf_len);
167
+ /* Search for the id in idset */
168
+ if ((ind = (TEXT **)bsearch(id_buf,idset,num_ids,sizeof(TEXT *),
169
+ bsearch_TEXT_strcmp)) != NULL){
170
+ rind = ind - idset;
171
+ if (refset[rind] != (TEXT *)0){
172
+ if (TEXT_strBcmp(in_buf,refset[rind],TEXT_strlen(in_buf))!= 0){
173
+ fprintf(stderr,"Error: double reference text for id '%s'\n",
174
+ id_buf);
175
+ failure=1;
176
+ }
177
+ } else {
178
+ refset[rind] = TEXT_strdup(in_buf);
179
+ num_ref++;
180
+ }
181
+ }
182
+ }
183
+ fclose(fp);
184
+
185
+ if (num_ref != num_ids){
186
+ failure=1;
187
+ fprintf(stderr,"Error: Not enough Reference files loaded\nMissing:\n");
188
+ for (i=0; i<num_ref; i++)
189
+ if (refset[i] == (TEXT *)0)
190
+ fprintf(stderr," %s\n",idset[i]);
191
+ }
192
+
193
+ /* space for the reference id's */
194
+ alloc_singZ(refids,num_ref,TEXT *,(TEXT *)0);
195
+ /* transfer the id's to the new array */
196
+ memcpy(refids,idset,sizeof(TEXT *) * num_ref);
197
+ /* free the idset array */
198
+ free_singarr(idset, TEXT *)
199
+
200
+ free_singarr(in_buf,TEXT);
201
+ free_singarr(id_buf,TEXT);
202
+
203
+ *rset = refset;
204
+ *refcnt = num_ref;
205
+ *refid = refids;
206
+
207
+ if (failure)
208
+ exit(1);
209
+ }
210
+
211
+ PATH *infer_word_seg_algo2(TEXT *ref, TEXT *hyp, NETWORK *hnet, int case_sense,char *id, char *lex_fname, int fcorr, int opt_del, int flags)
212
+ {
213
+ char *proc="infer_word_seg_algo2";
214
+ NETWORK *refnet, *hypnet;
215
+ PATH *path;
216
+ static TEXT_LIST *tl = (TEXT_LIST *)0;
217
+ static int max_word_len=1;
218
+ int char_align = (flags == INF_ASCII_TOO) ? CALI_ON : CALI_ON+CALI_NOASCII;
219
+
220
+ if (hyp != (TEXT *)0 && hnet != (NETWORK *)0){
221
+ fprintf(scfp,"Error: %s passed ambiguous arguments "
222
+ "for 'hyp' and 'hnet'\n",proc);
223
+ exit(1);
224
+ }
225
+
226
+ if (tl == (TEXT_LIST *)0){
227
+ int i, s;
228
+ if ((tl = load_TEXT_LIST(lex_fname,0)) == (TEXT_LIST *)0) {
229
+ fprintf(scfp,"Error: Can't load lexicon file '%s'\n",lex_fname);
230
+ exit(0);
231
+ }
232
+ /* compute the largest word, (in characters) in the TEXT_LIST */
233
+ for (i=0; i<tl->num; i++)
234
+ if ((s = TEXT_chrlen(tl->elem[i])) > max_word_len)
235
+ max_word_len = s;
236
+ }
237
+
238
+ {
239
+ TEXT *refCC = (case_sense ? TEXT_strdup(TEXT_str_to_master(ref, 1)) : ref);
240
+ if ((refnet = Network_create_from_TEXT(ref, "Reference Net",
241
+ print_WORD,
242
+ equal_WORD2,
243
+ release_WORD, null_alt_WORD,
244
+ opt_del_WORD,
245
+ copy_WORD, make_empty_WORD,
246
+ use_count_WORD))
247
+ == NULL_NETWORK){
248
+ fprintf(stderr,"Network_create_from_TEXT failed\n");
249
+ exit(1);
250
+ }
251
+ if (case_sense){
252
+ free_singarr(refCC, TEXT);
253
+ }
254
+ }
255
+
256
+ if (hyp != (TEXT *)0){
257
+ TEXT *hypCC = (case_sense ? TEXT_strdup(TEXT_str_to_master(hyp, 1)) : hyp);
258
+ if ((hypnet = Network_create_from_TEXT(hyp,"Hypothesis Net",
259
+ print_WORD,
260
+ equal_WORD2,
261
+ release_WORD, null_alt_WORD,
262
+ opt_del_WORD,
263
+ copy_WORD, make_empty_WORD,
264
+ use_count_WORD))
265
+ == NULL_NETWORK){
266
+ fprintf(stderr,"Network_create_from_TEXT failed\n");
267
+ exit(1);
268
+ }
269
+ if (case_sense){
270
+ free_singarr(hypCC, TEXT);
271
+ }
272
+ } else
273
+ hypnet = hnet;
274
+
275
+ if (opt_del){
276
+ Network_traverse(hypnet,NULL,0,decode_opt_del,0,0);
277
+ Network_traverse(refnet,NULL,0,decode_opt_del,0,0);
278
+ }
279
+
280
+ if (fcorr){
281
+ Network_traverse(hypnet,NULL,0,decode_fragment,0,0);
282
+ Network_traverse(refnet,NULL,0,decode_fragment,0,0);
283
+ }
284
+
285
+ Network_traverse(refnet,NULL,0,expand_words_to_chars,&char_align,0);
286
+
287
+ Network_fully_connect_cond(refnet, max_word_len, append_WORD_no_NULL,
288
+ WORD_in_TEXT_LIST, tl);
289
+
290
+ /* printf("-----------------\n");
291
+ Network_traverse(hypnet,NULL,0,print_arc,0,NT_CA_For+NT_Verbose);
292
+ Network_traverse(refnet,NULL,0,print_arc,0,NT_CA_For+NT_Verbose); */
293
+
294
+ Network_dpalign(refnet,hypnet,wwd_WORD,&path,FALSE);
295
+ PATH_add_utt_id(path,(char *)id);
296
+ PATH_set_sequence(path);
297
+ if (case_sense) BF_SET(path->attrib,PA_CASE_SENSE);
298
+
299
+ Network_destroy(refnet);
300
+ Network_destroy(hypnet);
301
+
302
+ /* free_TEXT_LIST (&tl); */
303
+ return(path);
304
+ }
305
+
306
+ PATH *infer_word_seg_algo1(TEXT *ref, TEXT *hyp, NETWORK *hnet, int case_sense,char *id, char *lex_fname, int fcorr, int opt_del, int flags)
307
+ {
308
+ char *proc="infer_word_seg_algo1";
309
+ NETWORK *refnet, *hypnet;
310
+ PATH *path;
311
+ static TEXT_LIST *tl = (TEXT_LIST *)0;
312
+ static int max_word_len=1;
313
+ int char_align = (flags == INF_ASCII_TOO) ? CALI_ON : CALI_ON+CALI_NOASCII;
314
+
315
+ if (hyp != (TEXT *)0 && hnet != (NETWORK *)0){
316
+ fprintf(scfp,"Error: %s passed ambiguous arguments "
317
+ "for 'hyp' and 'hnet'\n",proc);
318
+ exit(1);
319
+ }
320
+
321
+ if (tl == (TEXT_LIST *)0){
322
+ int i, s;
323
+ if ((tl = load_TEXT_LIST(lex_fname,0)) == (TEXT_LIST *)0) {
324
+ fprintf(scfp,"Error: Can't load lexicon file '%s'\n",lex_fname);
325
+ exit(0);
326
+ }
327
+ /* compute the largest word, (in characters) in the TEXT_LIST */
328
+ for (i=0; i<tl->num; i++)
329
+ if ((s = TEXT_chrlen(tl->elem[i])) > max_word_len)
330
+ max_word_len = s;
331
+ }
332
+
333
+ TEXT *refCC = (! case_sense ? TEXT_strdup(TEXT_str_to_master(ref, 1)) : ref);
334
+ //db=20;
335
+ if ((refnet = Network_create_from_TEXT(refCC, "Reference Net",
336
+ print_WORD,
337
+ equal_WORD2,
338
+ release_WORD, null_alt_WORD,
339
+ opt_del_WORD,
340
+ copy_WORD, make_empty_WORD,
341
+ use_count_WORD))
342
+ == NULL_NETWORK){
343
+ fprintf(stderr,"Network_create_from_TEXT failed\n");
344
+ exit(1);
345
+ }
346
+
347
+ if (! case_sense){
348
+ free_singarr(refCC, TEXT);
349
+ }
350
+ if (hyp != (TEXT *)0){
351
+ TEXT *hypCC = (! case_sense ? TEXT_strdup(TEXT_str_to_master(hyp, 1)) : hyp);
352
+ if ((hypnet = Network_create_from_TEXT(hypCC,"Hypothesis Net",
353
+ print_WORD,
354
+ equal_WORD2,
355
+ release_WORD, null_alt_WORD,
356
+ opt_del_WORD,
357
+ copy_WORD, make_empty_WORD,
358
+ use_count_WORD))
359
+ == NULL_NETWORK){
360
+ fprintf(stderr,"Network_create_from_TEXT failed\n");
361
+ exit(1);
362
+ }
363
+ if (! case_sense){
364
+ free_singarr(hypCC, TEXT);
365
+ }
366
+ } else
367
+ hypnet = hnet;
368
+
369
+ // Network_traverse(hypnet,NULL,0,print_arc,0,NT_CA_For+NT_Verbose);
370
+
371
+ if (opt_del){
372
+ Network_traverse(hypnet,NULL,0,decode_opt_del,0,0);
373
+ Network_traverse(refnet,NULL,0,decode_opt_del,0,0);
374
+ }
375
+
376
+ if (fcorr){
377
+ Network_traverse(hypnet,NULL,0,decode_fragment,0,0);
378
+ Network_traverse(refnet,NULL,0,decode_fragment,0,0);
379
+ }
380
+
381
+ // Network_traverse(hypnet,NULL,0,0c,0,NT_CA_For+NT_Verbose);
382
+ Network_traverse(hypnet,NULL,0,expand_words_to_chars,&char_align,0);
383
+ // Network_traverse(hypnet,NULL,0,print_arc,0,NT_CA_For+NT_Verbose);
384
+
385
+ Network_fully_connect_cond(hypnet, max_word_len, append_WORD_no_NULL,
386
+ WORD_in_TEXT_LIST, tl);
387
+
388
+ // printf("-----------------\n");
389
+ // Network_traverse(hypnet,NULL,0,print_arc,0,NT_CA_For+NT_Verbose);
390
+ // Network_traverse(refnet,NULL,0,print_arc,0,NT_CA_For+NT_Verbose);
391
+
392
+ Network_dpalign(refnet,hypnet,wwd_WORD,&path,FALSE);
393
+ PATH_add_utt_id(path,(char *)id);
394
+ PATH_set_sequence(path);
395
+ if (case_sense) BF_SET(path->attrib,PA_CASE_SENSE);
396
+
397
+ Network_destroy(refnet);
398
+ Network_destroy(hypnet);
399
+
400
+ /* free_TEXT_LIST (&tl); */
401
+ return(path);
402
+ }
403
+
404
+ PATH *network_dp_align_texts(TEXT *ref, NETWORK *rnet, TEXT *hyp, NETWORK *hnet, int char_align, int case_sense, char *id, int fcorr, int opt_del, int time_align, WWL *wwl, char *lm_file)
405
+ {
406
+ char *proc="network_dp_align_texts";
407
+ NETWORK *refnet, *hypnet;
408
+ PATH *path;
409
+
410
+ if (hyp != (TEXT *)0 && hnet != (NETWORK *)0){
411
+ fprintf(scfp,"Error: %s passed ambiguous arguments "
412
+ "for 'hyp' and 'hnet'\n",proc);
413
+ exit(1);
414
+ }
415
+
416
+ if (ref != (TEXT *)0 && rnet != (NETWORK *)0){
417
+ fprintf(scfp,"Error: %s passed ambiguous arguments "
418
+ "for 'ref' and 'rnet'\n",proc);
419
+ exit(1);
420
+ }
421
+ // printf("\nREF -> %s\n",ref);
422
+ // printf("HYP -> %s\n",hyp);
423
+ if (ref != (TEXT *)0){
424
+ TEXT *refCC = (! case_sense ? TEXT_strdup(TEXT_str_to_master(ref, 1)) : ref);
425
+
426
+ if ((refnet = Network_create_from_TEXT(refCC, "Reference Net",print_WORD,
427
+ equal_WORD2,
428
+ release_WORD, null_alt_WORD,
429
+ opt_del_WORD,
430
+ copy_WORD, make_empty_WORD,
431
+ use_count_WORD))
432
+ == NULL_NETWORK){
433
+ fprintf(stderr,"Network_create_from_TEXT failed\n");
434
+ exit(1);
435
+ }
436
+ if (! case_sense){
437
+ free_singarr(refCC, TEXT);
438
+ }
439
+ } else {
440
+ refnet = rnet;
441
+ }
442
+
443
+ if (hyp != (TEXT *)0){
444
+ TEXT *hypCC = (!case_sense ? TEXT_strdup(TEXT_str_to_master(hyp, 1)) : hyp);
445
+
446
+ if ((hypnet = Network_create_from_TEXT(hypCC,"Hypothesis Net",
447
+ print_WORD,
448
+ equal_WORD2,
449
+ release_WORD, null_alt_WORD,
450
+ opt_del_WORD,
451
+ copy_WORD, make_empty_WORD,
452
+ use_count_WORD))
453
+ == NULL_NETWORK){
454
+ fprintf(stderr,"Network_create_from_TEXT failed\n");
455
+ exit(1);
456
+ }
457
+ if (! case_sense){
458
+ free_singarr(hypCC, TEXT);
459
+ }
460
+ } else
461
+ hypnet = hnet;
462
+
463
+ if (opt_del){
464
+ Network_traverse(hypnet,NULL,0,decode_opt_del,0,0);
465
+ Network_traverse(refnet,NULL,0,decode_opt_del,0,0);
466
+ }
467
+
468
+ if (fcorr){
469
+ Network_traverse(hypnet,NULL,0,decode_fragment,0,0);
470
+ Network_traverse(refnet,NULL,0,decode_fragment,0,0);
471
+ }
472
+
473
+ if (char_align){
474
+ Network_traverse(hypnet,NULL,0,expand_words_to_chars,&char_align,0);
475
+ Network_traverse(refnet,NULL,0,expand_words_to_chars,&char_align,0);
476
+ }
477
+
478
+ if (wwl != (WWL *)0){
479
+ Network_traverse(hypnet,NULL,0,lookup_word_weight,wwl,0);
480
+ Network_traverse(refnet,NULL,0,lookup_word_weight,wwl,0);
481
+ }
482
+
483
+ if (lm_file != (char *)0){
484
+ Network_traverse(hypnet,NULL,0,lookup_lm_word_weight,lm_file,0);
485
+ Network_traverse(refnet,NULL,0,lookup_lm_word_weight,lm_file,0);
486
+ }
487
+
488
+ // Network_traverse(hypnet,NULL,0,print_arc,0,NT_CA_For+NT_Verbose);
489
+ // Network_traverse(refnet,NULL,0,print_arc,0,NT_CA_For+NT_Verbose);
490
+ Network_dpalign(refnet,hypnet,
491
+ ( (time_align) ? wwd_time_WORD :
492
+ ( ((wwl != (WWL *)0) || (lm_file != (char *)0)) ?
493
+ wwd_weight_WORD : wwd_WORD) ),
494
+ &path,FALSE);
495
+ PATH_add_utt_id(path,(char *)id);
496
+ PATH_set_sequence(path);
497
+ if (case_sense) BF_SET(path->attrib,PA_CASE_SENSE);
498
+ if (char_align) BF_SET(path->attrib,PA_CHAR_ALIGN);
499
+ if ((wwl != (WWL *)0) || (lm_file != (char *)0)) {
500
+ BF_SET(path->attrib,PA_HYP_WEIGHT);
501
+ BF_SET(path->attrib,PA_REF_WEIGHT);
502
+ }
503
+
504
+ Network_destroy(refnet);
505
+ Network_destroy(hypnet);
506
+
507
+ return(path);
508
+ }
509
+
510
+ SCORES *align_trans_mode_dp(char *ref_file, char *hyp_file, char *set_title, int keep_path, int case_sense, int feedback, int char_align, enum id_types idt, int infer_word_seg, char *lexicon, int fcorr, int opt_del, int inf_no_ascii, WWL *wwl, char *lm_file){
511
+ FILE *fp_hyp;
512
+ TEXT *hyp_buff, *hyp_id, *spkr_id;
513
+ int hyp_buff_len=LOAD_BUFF_LEN, hyp_id_len=LOAD_BUFF_LEN;
514
+ int spkr_id_len=LOAD_BUFF_LEN;
515
+ PATH *path;
516
+ SCORES *scor;
517
+ int spk, rind, last_spk=0;
518
+ TEXT **reftran, **refid, **ind;
519
+ int refcnt;
520
+
521
+ alloc_singZ(hyp_buff,hyp_buff_len,TEXT,'\0');
522
+ alloc_singZ(hyp_id,hyp_id_len,TEXT,'\0');
523
+ alloc_singZ(spkr_id,spkr_id_len,TEXT,'\0');
524
+
525
+ if ((hyp_file == NULL) || (*hyp_file == '\0') ||
526
+ ((fp_hyp = fopen(hyp_file,"r")) == NULL)){
527
+ fprintf(stderr,"Can't open input hypothesis file %s\n",hyp_file);
528
+ exit(1);
529
+ }
530
+
531
+ scor = SCORES_init(set_title,20);
532
+ scor->ref_fname = (char *)TEXT_strdup((TEXT *)ref_file);
533
+ scor->hyp_fname = (char *)TEXT_strdup((TEXT *)hyp_file);
534
+ scor->creation_date = get_date();
535
+ scor->frag_corr = fcorr;
536
+ scor->opt_del = opt_del;
537
+ if (wwl != (WWL*)0) {
538
+ scor->weight_ali = 1;
539
+ scor->weight_file =
540
+ (char *)TEXT_strdup((TEXT*)rsprintf("%s Column \"%s\"",wwl->filename,
541
+ wwl->weight_desc[0]));
542
+ } else if (lm_file != (char *)0) {
543
+ scor->weight_ali = 1;
544
+ scor->weight_file = (char *)TEXT_strdup((TEXT*)lm_file);
545
+ } else
546
+ scor->weight_ali = 0;
547
+
548
+ load_refs(scor, hyp_file, ref_file, &reftran, &refid, &refcnt, case_sense);
549
+
550
+ while (!feof(fp_hyp)){
551
+ *hyp_buff = *(hyp_buff+1) = COMMENT_CHAR;
552
+ *(hyp_buff+2) = NULL_TEXT;
553
+ while (!feof(fp_hyp) && (parse_input_comment_line(scor,hyp_buff) ||
554
+ TEXT_is_comment_info(hyp_buff) ||
555
+ TEXT_is_empty(hyp_buff)))
556
+ if (TEXT_ensure_fgets(&hyp_buff,&hyp_buff_len,fp_hyp) == NULL)
557
+ *hyp_buff = '\0';
558
+ if (feof(fp_hyp))
559
+ break;
560
+
561
+ remove_id(hyp_buff,&hyp_id,&hyp_id_len);
562
+ if (!case_sense) TEXT_str_case_change_with_mem_expand(&hyp_id, &hyp_id_len, 1);
563
+
564
+ extract_speaker(hyp_id,spkr_id,idt);
565
+ spk = SCORES_get_grp(scor,(char *)spkr_id);
566
+
567
+ if (feedback >= 1){
568
+ if (spk != last_spk) { printf("\n"); last_spk = spk; }
569
+ printf("\r Alignment# %d for speaker %s ",
570
+ scor->grp[spk].nsent+1,spkr_id);
571
+ fflush(stdout);
572
+ }
573
+
574
+ if ((ind = (TEXT **)bsearch(hyp_id,refid,refcnt,sizeof(TEXT *),
575
+ bsearch_TEXT_strcmp)) == NULL){
576
+ fprintf(stderr,"Error: Unable to locate Ref transcript for '%s'\n",
577
+ hyp_id);
578
+ exit(1);
579
+ }
580
+ rind = ind - refid;
581
+
582
+ if (feedback >= 100){
583
+ printf("\n HYP -> %s\n",hyp_buff);
584
+ printf(" REF -> %s\n",reftran[rind]);
585
+ fflush(stdout);
586
+ }
587
+ if (infer_word_seg == 0)
588
+ path = network_dp_align_texts(reftran[rind], (NETWORK *)0,
589
+ hyp_buff, (NETWORK *)0,
590
+ char_align, case_sense,
591
+ (char *)hyp_id, fcorr, opt_del, FALSE, wwl, lm_file);
592
+ else if (infer_word_seg == INF_SEG_ALGO1)
593
+ path = infer_word_seg_algo1(reftran[rind], hyp_buff, (NETWORK *)0,
594
+ case_sense, (char *)hyp_id, lexicon,
595
+ fcorr, opt_del, inf_no_ascii);
596
+ else if (infer_word_seg == INF_SEG_ALGO2)
597
+ path = infer_word_seg_algo2(reftran[rind], hyp_buff, (NETWORK *)0,
598
+ case_sense, (char *)hyp_id, lexicon,
599
+ fcorr, opt_del, inf_no_ascii);
600
+ else{
601
+ fprintf(scfp,"Error: unknown alignment procedure\n");
602
+ exit(1);
603
+ }
604
+
605
+ if (feedback >= 2){
606
+ printf("\n");
607
+ PATH_print(path,stdout,199);
608
+ printf("\n");
609
+ }
610
+
611
+ add_PATH_score(scor,path,spk, keep_path);
612
+
613
+ if (!keep_path)
614
+ PATH_free(path);
615
+ }
616
+ if (feedback >= 1)
617
+ printf("\n\n");
618
+
619
+ free_singarr(hyp_buff,TEXT);
620
+ free_singarr(hyp_id,TEXT);
621
+ free_singarr(spkr_id,TEXT);
622
+ free_refs(&reftran, &refid, refcnt);
623
+ fclose(fp_hyp);
624
+
625
+ return(scor);
626
+ }
627
+
628
+
629
+ /* This function, called by the network travers function, will set the */
630
+ /* duration of the word to *(double *)ptr */
631
+ void set_word_duration(ARC *arc, void *ptr){
632
+ WORD *tw = (WORD *)(arc->data);
633
+ tw->T_dur = *(double *)ptr;
634
+ }
635
+
636
+ /* This function, called by the network traverse function, will set the */
637
+ /* words start to *(double *)ptr, then set T2 to be T1+dur, then */
638
+ /* increment *(double *)ptr by dur. */
639
+ void set_word_start(ARC *arc, void *ptr){
640
+ WORD *tw = (WORD *)(arc->data);
641
+ tw->T1 = *(double *)ptr;
642
+ tw->T2 = tw->T_dur + tw->T1;
643
+ *(double *)ptr += tw->T_dur;
644
+ }
645
+
646
+ /* This function, called by the network traverse function, will set the */
647
+ /* word's confidence score to *(double *)ptr */
648
+ void set_word_conf(ARC *arc, void *ptr){
649
+ WORD *tw = (WORD *)(arc->data);
650
+ tw->conf = *(double *)ptr;
651
+ }
652
+
653
+ /* This function, called by the network traverse function, will set the */
654
+ /* word's optionally deletable flag to *(int *)ptr */
655
+ void set_word_opt_del(ARC *arc, void *ptr){
656
+ WORD *tw = (WORD *)(arc->data);
657
+ TEXT *ot;
658
+
659
+ if (*(int *)ptr){
660
+ /* re-make the optionally deletable text */
661
+ ot = tw->value;
662
+ tw->value = TEXT_strdup((TEXT *)rsprintf(WORD_OPT_DEL_PRE_STR "%s"
663
+ WORD_OPT_DEL_POST_STR,ot));
664
+ TEXT_free(ot);
665
+ }
666
+ }
667
+
668
+ void expand_words_to_chars(ARC *arc, void *ptr){
669
+ char *proc = "expand_words_to_chars";
670
+ WORD *tw = (WORD *)(arc->data);
671
+ static TEXT *chars=(TEXT *)0, *charsEsc;
672
+ static int chars_len=100;
673
+ NETWORK *subnet;
674
+ char buf[20];
675
+ static int alt=1;
676
+
677
+ if (chars == (TEXT *)0) alloc_singZ(chars,chars_len,TEXT,'\0');
678
+ /* it the string is already a single letter, return */
679
+ if (TEXT_strlen(tw->value) <= 1)
680
+ return;
681
+
682
+ if (db >= 5) {
683
+ printf("%s: String length > 1\n",proc);
684
+ arc->net->arc_func.print(arc->data);
685
+ }
686
+ // arc->net->arc_func.print(arc->data);
687
+ sprintf(buf,"expand-net %d",alt);
688
+ TEXT_separate_chars((!tw->opt_del) ? tw->value : tw->intern_value,
689
+ &chars,&chars_len,*((int *)ptr));
690
+
691
+ // printf(" from /%s/ comes /%s/\n",(!tw->opt_del) ? tw->value : tw->intern_value, chars);
692
+
693
+ // Escape the semicolon
694
+ alloc_singZ(charsEsc, chars_len*2+1, TEXT, NULL_TEXT);
695
+ TEXT_strcpy_escaped(charsEsc, chars, ';');
696
+ // printf(" and escaped /%s/\n", charsEsc);
697
+
698
+ /* Fix, it wasn't enough check to see if the there were any spaces */
699
+ if (TEXT_strcmp(chars,tw->value) != 0){
700
+ subnet = Network_create_from_TEXT(charsEsc, buf, arc->net->arc_func.print,
701
+ arc->net->arc_func.equal,
702
+ arc->net->arc_func.destroy,
703
+ arc->net->arc_func.is_null_alt,
704
+ arc->net->arc_func.is_opt_del,
705
+ arc->net->arc_func.copy,
706
+ arc->net->arc_func.make_empty,
707
+ arc->net->arc_func.use_count);
708
+ if (subnet == NULL_NETWORK){
709
+ fprintf(scfp,"proc %s: Internal error. Unable to expand words"
710
+ " to characters\n",proc);
711
+ return;
712
+ }
713
+ /* traverse the network, setting the character times to equal */
714
+ /* durations based on the original word */
715
+ {
716
+ double dur = tw->T_dur/subnet->arc_count, t1 = tw->T1, conf = tw->conf;
717
+ int od = tw->opt_del;
718
+ Network_traverse(subnet,NULL,0,set_word_duration,&dur,0);
719
+ Network_traverse(subnet,NULL,0,set_word_start,&t1,0);
720
+ Network_traverse(subnet,NULL,0,set_word_conf,&conf,0);
721
+ if (od){
722
+ Network_traverse(subnet,NULL,0,set_word_opt_del,&od,0);
723
+ Network_traverse(subnet,NULL,0,decode_opt_del,0,0);
724
+ }
725
+ }
726
+ Network_merge_network(arc->from_node,arc->to_node,subnet);
727
+ Network_delete_arc(arc);
728
+ alt++;
729
+ }
730
+ free_singarr(charsEsc, TEXT);
731
+ }
732
+
733
+
734
+
735
+ void lookup_word_weight(ARC *arc, void *ptr){
736
+ WORD *tw = (WORD *)(arc->data);
737
+ WWL *wwl = (WWL *)ptr;
738
+
739
+ if (tw->value == (TEXT *)0)
740
+ tw->weight = 0.0;
741
+ else if (TEXT_strcmp(tw->value,(TEXT *)"@") == 0)
742
+ tw->weight = 0.0;
743
+ else if (tw->opt_del)
744
+ tw->weight = 0.0;
745
+ else
746
+ tw->weight = Weight_wwl((tw->opt_del ? tw->intern_value : tw->value), wwl);
747
+
748
+ return;
749
+ }
750
+
751
+
752
+ void decode_opt_del(ARC *arc, void *ptr){
753
+ WORD *tw = (WORD *)(arc->data);
754
+ int len;
755
+
756
+ if (tw->value == (TEXT *)0) return;
757
+ len = TEXT_strlen(tw->value);
758
+
759
+ if ((*(tw->value + len - 1) == WORD_OPT_DEL_POST_CHAR) &&
760
+ (*(tw->value) == WORD_OPT_DEL_PRE_CHAR)){
761
+ tw->opt_del = TRUE;
762
+ tw->intern_value = TEXT_strBdup(tw->value + 1,len - 2);
763
+ }
764
+ return;
765
+ }
766
+
767
+ void decode_fragment(ARC *arc, void *ptr){
768
+ WORD *tw = (WORD *)(arc->data);
769
+ int len;
770
+
771
+ if (tw->value == (TEXT *)0) return;
772
+ len = TEXT_strlen(tw->value);
773
+ if (((*(tw->value + len - 1) == WORD_FRAG_CHAR) ||
774
+ (*(tw->value ) == WORD_FRAG_CHAR)) ||
775
+ (tw->opt_del &&
776
+ (*(tw->value + len - 2) == WORD_FRAG_CHAR)))
777
+ tw->frag_corr = TRUE;
778
+
779
+ return;
780
+ }
781
+
782
+
783
+ /**********************************************************************/
784
+ /************ USE GNU-DIFF to compute the alignments *************/
785
+ /**********************************************************************/
786
+
787
+ void create_word_lists(SCORES *sc, TEXT **reftran, TEXT **refid, int refcnt, char *hyp_file, char *out_ref, char *out_hyp, int *num_hyp, int case_sense);
788
+ void process_diff_line(TEXT *diff_out, PATH *path, TEXT **firsttoken);
789
+ void set_temp_files(char *refwords, char *hypwords);
790
+
791
+ void create_word_lists(SCORES *sc, TEXT **reftran, TEXT **refid, int refcnt, char *hyp_file, char *out_ref, char *out_hyp, int *num_hyp, int case_sense){
792
+ FILE *fp_hyp, *fp_out_ref, *fp_out_hyp;
793
+ TEXT *hyp_buff, *hyp_id, *ctext, *tbuf;
794
+ int hyp_buff_len=LOAD_BUFF_LEN, hyp_id_len=LOAD_BUFF_LEN;
795
+ int tbuf_len=100;
796
+ int rind;
797
+ TEXT **ind;
798
+
799
+ alloc_singZ(tbuf,tbuf_len,TEXT,'\0');
800
+ alloc_singZ(hyp_buff,hyp_buff_len,TEXT,'\0');
801
+ alloc_singZ(hyp_id,hyp_id_len,TEXT,'\0');
802
+
803
+ if ((fp_hyp = fopen(hyp_file,"r")) == NULL){
804
+ fprintf(stderr,"Can't open input hypothesis file %s\n",hyp_file);
805
+ exit(1);
806
+ }
807
+
808
+ if ((fp_out_hyp=fopen(out_hyp,"w")) == NULL){
809
+ fprintf(stderr,"Error: Unable to open Hypothesis word file '%s'\n",
810
+ out_hyp);
811
+ exit(1);
812
+ }
813
+ if ((fp_out_ref=fopen(out_ref,"w")) == NULL){
814
+ fprintf(stderr,"Error: Unable to open Reference word file '%s'\n",
815
+ out_ref);
816
+ exit(1);
817
+ }
818
+
819
+ while (!feof(fp_hyp)){
820
+ *hyp_buff = *(hyp_buff+1) = COMMENT_CHAR;
821
+ *(hyp_buff+2) = NULL_TEXT;
822
+
823
+ while (!feof(fp_hyp) && (parse_input_comment_line(sc,hyp_buff) ||
824
+ TEXT_is_comment_info(hyp_buff) ||
825
+ TEXT_is_empty(hyp_buff)))
826
+ if (TEXT_ensure_fgets(&hyp_buff,&hyp_buff_len,fp_hyp) == NULL)
827
+ *hyp_buff = '\0';
828
+
829
+ if (feof(fp_hyp))
830
+ break;
831
+
832
+ (*num_hyp) ++;
833
+
834
+ if (!case_sense)
835
+ TEXT_str_case_change_with_mem_expand(&hyp_buff, &hyp_buff_len, 1);
836
+
837
+ remove_id(hyp_buff,&hyp_id,&hyp_id_len);
838
+ if ((ind = (TEXT **)bsearch(hyp_id,refid,refcnt,sizeof(TEXT *),
839
+ bsearch_TEXT_strcmp)) == NULL){
840
+ fprintf(stderr,"Error: Unable to locate Ref transcript for '%s'\n",
841
+ hyp_id);
842
+ exit(1);
843
+ }
844
+ rind = ind - refid;
845
+
846
+ /* Write each individual word to a file */
847
+ if (TEXT_strlen(reftran[rind]) > tbuf_len+1){
848
+ free_singarr(tbuf,TEXT);
849
+ tbuf = TEXT_strdup(reftran[rind]);
850
+ tbuf_len = TEXT_strlen(tbuf);
851
+ } else
852
+ TEXT_strcpy(tbuf,reftran[rind]);
853
+
854
+ ctext = tokenize_TEXT_first_alt(tbuf,(TEXT *)" \t\n");
855
+ while (ctext != NULL) {
856
+ fprintf(fp_out_ref,"%s\n",ctext);
857
+ ctext = tokenize_TEXT_first_alt(NULL,(TEXT *)" \t\n");
858
+ }
859
+
860
+ ctext = TEXT_strtok(hyp_buff,(TEXT *)" \t\n");
861
+ while (ctext != NULL) {
862
+ fprintf(fp_out_hyp,"%s\n",ctext);
863
+ ctext = TEXT_strtok(NULL,(TEXT *)" \t\n");
864
+ }
865
+ }
866
+
867
+ fclose(fp_out_ref);
868
+ fclose(fp_out_hyp);
869
+ fclose(fp_hyp);
870
+ free_singarr(hyp_buff,TEXT);
871
+ free_singarr(hyp_id,TEXT);
872
+ free_singarr(tbuf,TEXT);
873
+ }
874
+
875
+ void process_diff_line(TEXT *diff_out, PATH *path, TEXT **firsttoken){
876
+ static TEXT s1[100],s2[100],s3[100];
877
+ int iret;
878
+ WORD *rwd, *hwd;
879
+
880
+ check_space_in_PATH(path);
881
+ *s1 = *s2 = *s3 = '\0';
882
+ iret = sscanf((char *)diff_out,
883
+ "%s %s %s",(char *)s1,(char *)s2,(char *)s3);
884
+ *firsttoken = s1;
885
+
886
+ if (iret == 2 && TEXT_strcmp(s1,s2) == 0)
887
+ path->pset[path->num].eval = P_CORR;
888
+ else if (iret == 2 && TEXT_strcmp(s1,(TEXT *)">") == 0)
889
+ path->pset[path->num].eval = P_INS;
890
+ else if (iret == 3)
891
+ path->pset[path->num].eval = P_SUB;
892
+ else
893
+ path->pset[path->num].eval = P_DEL;
894
+
895
+ path->pset[path->num].b_ptr = path->pset[path->num].a_ptr = (void *)0;
896
+
897
+ switch (path->pset[path->num].eval){
898
+ case P_CORR:
899
+ case P_DEL:
900
+ case P_SUB:
901
+ rwd = new_WORD(s1, -1, 0.0, 0.0, 0.0, (TEXT *)0, (TEXT *)0, 0, 0, -1.0);
902
+ path->pset[path->num].a_ptr = rwd;
903
+ case P_INS:
904
+ ;
905
+ }
906
+ switch (path->pset[path->num].eval){
907
+ case P_CORR:
908
+ case P_INS:
909
+ case P_SUB:
910
+ hwd = (WORD *)0;
911
+ switch (path->pset[path->num].eval){
912
+ case P_CORR:
913
+ case P_INS:
914
+ hwd = new_WORD(s2, -1, 0.0, 0.0, 0.0,(TEXT *)0, (TEXT *)0, 0, 0, -1.0); break;
915
+ case P_SUB:
916
+ hwd = new_WORD(s3, -1, 0.0, 0.0, 0.0,(TEXT *)0, (TEXT *)0, 0, 0, -1.0); break;
917
+ case P_DEL:
918
+ hwd = new_WORD((TEXT *)0, -1, 0.0, 0.0, 0.0,(TEXT *)0, (TEXT *)0, 0, 0, -1.0);
919
+ break;
920
+ }
921
+ if (hwd == (WORD *)0){
922
+ fprintf(stderr,"Error: Failed to alloc word in process_diff_line\n");
923
+ exit(1);
924
+ }
925
+ path->pset[path->num].b_ptr = hwd;
926
+ case P_DEL:
927
+ ;
928
+ }
929
+
930
+ path->num++;
931
+ }
932
+
933
+ void set_temp_files(char *refwords, char *hypwords){
934
+ int pid = getpid();
935
+ int max=30, n=0, fail;
936
+ struct stat fileinfo;
937
+
938
+ do {
939
+ sprintf(refwords,"/tmp/ref.%d",pid+n);
940
+ sprintf(hypwords,"/tmp/hyp.%d",pid+n);
941
+ n++;
942
+ fail = (stat(refwords,&fileinfo) == 0) ||
943
+ (stat(hypwords,&fileinfo) == 0);
944
+ } while (fail && (n < max));
945
+ if (fail){
946
+ fprintf(stderr,"Can't locate temp file names. Searched /tmp/ref.[%d-%d]\n",
947
+ pid,pid+n);
948
+ exit(1);
949
+ }
950
+ }
951
+
952
+ SCORES *align_trans_mode_diff(char *ref_file, char *hyp_file, char *set_title, int keep_path, int case_sense, int feedback, enum id_types idt){
953
+ FILE *fp_hyp, *fp_diff;
954
+ TEXT *hyp_buff, *hyp_id, *spkr_id, *diff_out;
955
+ int hyp_buff_len=LOAD_BUFF_LEN, hyp_id_len=LOAD_BUFF_LEN;
956
+ int spkr_id_len=LOAD_BUFF_LEN, diff_out_len=LOAD_BUFF_LEN;
957
+ PATH *path;
958
+ SCORES *scor;
959
+ int spk, rind;
960
+ TEXT **reftran, **refid, **ind;
961
+ TEXT *firsttoken;
962
+ int refcnt, num_hyp=0;
963
+ TEXT *ctext = hyp_buff; /* current position is text string */
964
+ char refwords[100], hypwords[100];
965
+
966
+ alloc_singZ(diff_out,diff_out_len,TEXT,'\0');
967
+ alloc_singZ(hyp_buff,hyp_buff_len,TEXT,'\0');
968
+ alloc_singZ(hyp_id,hyp_id_len,TEXT,'\0');
969
+ alloc_singZ(spkr_id,spkr_id_len,TEXT,'\0');
970
+
971
+ set_temp_files(refwords, hypwords);
972
+
973
+ /* initialize the score structure */
974
+ scor = SCORES_init(set_title,20);
975
+ scor->ref_fname = (char *)TEXT_strdup((TEXT *)ref_file);
976
+ scor->hyp_fname = (char *)TEXT_strdup((TEXT *)hyp_file);
977
+ scor->creation_date = get_date();
978
+
979
+ /* load the required reference sentences */
980
+ if (feedback >= 1) printf(" Loading transcripts\n");
981
+ load_refs(scor, hyp_file, ref_file, &reftran, &refid, &refcnt, case_sense);
982
+
983
+ /* create a file of words for both the ref and hyp */
984
+ create_word_lists(scor, reftran, refid, refcnt, hyp_file,
985
+ refwords, hypwords, &num_hyp, case_sense);
986
+
987
+ /* use readpipe to open a process without creating a temporary file */
988
+ if (feedback >= 1) printf(" Executing diff\n");
989
+ if ((fp_diff = readpipe (DIFF_PROGRAM, "-y",refwords,
990
+ hypwords, NULL)) ==NULL){
991
+ fprintf(stderr,"Error: Execution of 'diff' failed\n");
992
+ exit(1);
993
+ }
994
+
995
+ if ((fp_hyp = fopen(hyp_file,"r")) == NULL){
996
+ fprintf(stderr,"Can't open input hypothesis file %s\n",hyp_file);
997
+ exit(1);
998
+ }
999
+ while (!feof(fp_hyp)){
1000
+ *hyp_buff = *(hyp_buff+1) = COMMENT_CHAR;
1001
+ *(hyp_buff+2) = NULL_TEXT;
1002
+
1003
+ while (!feof(fp_hyp) && (parse_input_comment_line(scor,hyp_buff) ||
1004
+ TEXT_is_comment_info(hyp_buff) ||
1005
+ TEXT_is_empty(hyp_buff)))
1006
+ if (TEXT_ensure_fgets(&hyp_buff,&hyp_buff_len,fp_hyp) == NULL)
1007
+ *hyp_buff = '\0';
1008
+
1009
+ if (feof(fp_hyp)) break;
1010
+ if (!case_sense) TEXT_str_case_change_with_mem_expand(&hyp_buff, &hyp_buff_len, 1);
1011
+ remove_id(hyp_buff,&hyp_id,&hyp_id_len);
1012
+ extract_speaker(hyp_id,spkr_id,idt);
1013
+ spk = SCORES_get_grp(scor,(char *)spkr_id);
1014
+
1015
+ if ((ind = (TEXT **)bsearch(hyp_id,refid,refcnt,sizeof(TEXT *),
1016
+ bsearch_TEXT_strcmp)) == NULL){
1017
+ fprintf(stderr,"Error: Unable to locate Ref transcript for '%s'\n",
1018
+ hyp_id);
1019
+ exit(1);
1020
+ }
1021
+ rind = ind - refid;
1022
+ --num_hyp;
1023
+
1024
+ if (feedback >= 3)
1025
+ printf("REF: %s\nHYP: %s\n",reftran[rind],hyp_buff);
1026
+
1027
+ path = PATH_alloc(100);
1028
+
1029
+ ctext = tokenize_TEXT_first_alt(reftran[rind],(TEXT *)" \t\n");
1030
+ while (ctext != NULL) {
1031
+ do {
1032
+ check_space_in_PATH(path);
1033
+ if (TEXT_ensure_fgets(&diff_out,&diff_out_len,fp_diff) ==
1034
+ NULL)
1035
+ *diff_out = '\0';
1036
+ if (feof(fp_diff)) break;
1037
+ process_diff_line(diff_out,path,&firsttoken);
1038
+ } while (!feof(fp_diff) &&
1039
+ ((TEXT_strcmp(firsttoken,ctext) != 0) || num_hyp==0));
1040
+ ctext = tokenize_TEXT_first_alt(NULL,(TEXT *)" \t\n");
1041
+ }
1042
+
1043
+ PATH_add_utt_id(path,(char *)hyp_id);
1044
+ PATH_set_sequence(path);
1045
+ if (case_sense) BF_SET(path->attrib,PA_CASE_SENSE);
1046
+
1047
+ if (feedback >= 2){
1048
+ printf("\n");
1049
+ PATH_print(path,stdout,199);
1050
+ printf("\n");
1051
+ }
1052
+
1053
+ add_PATH_score(scor,path,spk, keep_path);
1054
+
1055
+ if (!keep_path) PATH_free(path);
1056
+ }
1057
+ fclose(fp_diff);
1058
+ fclose(fp_hyp);
1059
+
1060
+ if (num_hyp != 0){
1061
+ fprintf(stderr,"Error: Unexpected number of output utts. Missing %d\n",num_hyp);
1062
+ exit(1);
1063
+ }
1064
+
1065
+ free_singarr(diff_out,TEXT);
1066
+ free_singarr(hyp_buff,TEXT);
1067
+ free_singarr(hyp_id,TEXT);
1068
+ free_singarr(spkr_id,TEXT);
1069
+ free_refs(&reftran, &refid, refcnt);
1070
+
1071
+ unlink(refwords);
1072
+ unlink(hypwords);
1073
+ return(scor);
1074
+ }
1075
+
1076
+ SCORES *align_ctm_to_stm_diff(char *ref_file, char *hyp_file, char *set_title, int keep_path, int case_sense, int feedback, enum id_types idt){
1077
+ char *proc="align_ctm_to_stm";
1078
+ FILE *fp_ref, *fp_hyp;
1079
+ WTOKE_STR1 *hyp_segs;
1080
+ int ref_eof, ref_err, hyp_eof, hyp_err;
1081
+ int hyp_end_chan1, ref_end_chan1;
1082
+ int hyp_end_chan2, ref_end_chan2;
1083
+ int just_read, hyp_file_end, ref_file_end;
1084
+ int number_of_channels;
1085
+ int i;
1086
+ PATH *path;
1087
+ STM *stm;
1088
+ SCORES *scor;
1089
+ int spkr, r;
1090
+ char refwords[100], hypwords[100];
1091
+ TEXT *diff_out, *firsttoken, *ctext;
1092
+ static int diff_out_len=100;
1093
+ FILE *fp_diff;
1094
+ int pdb = 0;
1095
+
1096
+ /* allocate memory */
1097
+ hyp_segs = WTOKE_STR1_init(hyp_file);
1098
+ scor = SCORES_init(set_title,20);
1099
+ scor->ref_fname = (char *)TEXT_strdup((TEXT *)ref_file);
1100
+ scor->hyp_fname = (char *)TEXT_strdup((TEXT *)hyp_file);
1101
+ scor->creation_date = get_date();
1102
+
1103
+ alloc_singZ(diff_out,diff_out_len,TEXT,'\0');
1104
+
1105
+ set_temp_files(refwords, hypwords);
1106
+
1107
+ if ((fp_hyp = fopen(hyp_file,"r")) == NULL){
1108
+ fprintf(stderr,"Can't open input hypothesis file %s\n",hyp_file);
1109
+ exit(1);
1110
+ }
1111
+ if ((fp_ref = fopen(ref_file,"r")) == NULL){
1112
+ fprintf(stderr,"Can't open input reference file %s\n",ref_file);
1113
+ exit(1);
1114
+ }
1115
+
1116
+ if ((stm = alloc_STM(200)) == (STM *)0) {
1117
+ fprintf(stderr,"%s: Failed to alloc STM struct\n",proc);
1118
+ exit(1);
1119
+ }
1120
+ hyp_eof = ref_eof = 0;
1121
+ do {
1122
+ do {
1123
+ locate_WTOKE_boundary(hyp_segs, hyp_segs->s, 1, 0, &hyp_file_end);
1124
+ just_read = 0;
1125
+ if ((hyp_file_end == hyp_segs->n) && !hyp_eof){
1126
+ fill_mark_struct(fp_hyp,hyp_segs,hyp_file,&hyp_eof,&hyp_err,
1127
+ case_sense);
1128
+ if (hyp_err != 0){
1129
+ fprintf(stdout,"; *Err: Error detected in hyp file '%s'\n",
1130
+ hyp_file);
1131
+ exit(1);
1132
+ }
1133
+ just_read = 1;
1134
+ }
1135
+ } while (just_read);
1136
+ just_read = 0;
1137
+ do {
1138
+ locate_STM_boundary(stm, stm->s, 1, 0, &ref_file_end);
1139
+ if ((ref_file_end == stm->num) && !ref_eof){
1140
+ if (just_read == 1){
1141
+ just_read = 0;
1142
+ expand_STM(stm);
1143
+ }
1144
+ fill_STM(fp_ref, stm, ref_file, &ref_eof, case_sense,&ref_err);
1145
+ if (hyp_err != 0){
1146
+ fprintf(stdout,"; *Err: Error detected in hyp file '%s'\n",
1147
+ hyp_file);
1148
+ exit(1);
1149
+ }
1150
+ just_read = 1;
1151
+ } else
1152
+ just_read = 0;
1153
+ } while (just_read);
1154
+
1155
+ /* find the end of the second channel for the hyp file */
1156
+ locate_WTOKE_boundary(hyp_segs, hyp_segs->s, 1, 1, &hyp_end_chan1);
1157
+ if (hyp_end_chan1+1 < hyp_segs->n &&
1158
+ strcmp(hyp_segs->word[hyp_segs->s].conv,
1159
+ hyp_segs->word[hyp_end_chan1+1].conv)==0){
1160
+ locate_WTOKE_boundary(hyp_segs,hyp_end_chan1+1,1,1,&hyp_end_chan2);
1161
+ number_of_channels = 2;
1162
+ } else {
1163
+ /* There was no second channel */
1164
+ hyp_end_chan2 = hyp_end_chan1;
1165
+ number_of_channels = 1;
1166
+ }
1167
+
1168
+ /* find the end of the second channel for the ref file */
1169
+ locate_STM_boundary(stm, stm->s, 1, 1, &ref_end_chan1);
1170
+ if (ref_end_chan1+1 < stm->num &&
1171
+ TEXT_strcmp(stm->seg[stm->s].file,
1172
+ stm->seg[ref_end_chan1+1].file)==0){
1173
+ if (number_of_channels != 2){
1174
+ fprintf(stderr,"%s: Channel Mis-match, 1 in Hyp, 2 in Ref\n",
1175
+ proc);
1176
+ return((SCORES *)0);
1177
+ }
1178
+ locate_STM_boundary(stm, ref_end_chan1+1, 1, 1, &ref_end_chan2);
1179
+ } else {
1180
+ /* There was no second channel */
1181
+ if (number_of_channels != 1){
1182
+ fprintf(stderr,"%s: Channel Mis-match, 2 in Hyp, 1 in Ref\n",
1183
+ proc);
1184
+ return((SCORES *)0);
1185
+ }
1186
+ ref_end_chan2 = ref_end_chan1;
1187
+ }
1188
+
1189
+ /* give some user feedback */
1190
+ if (feedback >= 1)
1191
+ printf(" Performing alignments for file '%s'.\n",
1192
+ stm->seg[stm->s].file);
1193
+ if (db+pdb >= 5){
1194
+ printf("%s: hyp CTM File Range [%d,%d]",
1195
+ proc,hyp_segs->s,hyp_file_end);
1196
+ printf(" Chan1 Range[%d,%d] ",hyp_segs->s,hyp_end_chan1);
1197
+ printf(" Chan2 Range[%d,%d]\n",hyp_end_chan1+1,hyp_end_chan2);
1198
+ if (db+pdb >= 10){
1199
+ dump_word_tokens2(hyp_segs, hyp_segs->s, hyp_file_end);
1200
+ printf("\n");
1201
+ }
1202
+ printf("%s: ref STM File Range [%d,%d]",proc,stm->s,ref_file_end);
1203
+ printf(" Chan1 Range[%d,%d] ",stm->s, ref_end_chan1);
1204
+ printf(" Chan2 Range[%d,%d]\n",ref_end_chan1+1,ref_end_chan2);
1205
+ if (db+pdb >= 10) dump_STM(stm, stm->s, ref_file_end);
1206
+ printf("\n");
1207
+ }
1208
+ /* Align each channel using diff */
1209
+ for (i=0; i<number_of_channels; i++){
1210
+ int h_st, h_end, r_st, r_end;
1211
+
1212
+ if (db+pdb >= 5) printf("\n%s: Starting Channel %d\n",proc,i);
1213
+ if (i==0){
1214
+ h_st = hyp_segs->s; h_end = hyp_end_chan1;
1215
+ r_st = stm->s; r_end = ref_end_chan1;
1216
+ } else {
1217
+ h_st = hyp_end_chan1+1; h_end = hyp_end_chan2;
1218
+ r_st = ref_end_chan1+1; r_end = ref_end_chan2;
1219
+ }
1220
+
1221
+ if (strcmp(hyp_segs->word[h_st].conv,
1222
+ (char *)stm->seg[r_st].file) != 0){
1223
+ fprintf(stderr,"%s: File identifiers do not match,\nhyp ",proc);
1224
+ fprintf(stderr,"file '%s' and ref file '%s' not synchronized\n",
1225
+ hyp_segs->word[h_st].conv,stm->seg[r_st].file);
1226
+ return((SCORES *)0);
1227
+ }
1228
+ if (strcmp(hyp_segs->word[h_st].turn,
1229
+ (char *)stm->seg[r_st].chan) != 0){
1230
+ fprintf(stderr,"%s: channel identifiers do not match, ",proc);
1231
+ fprintf(stderr,"hyp file '%s' and ref file '%s' not",
1232
+ hyp_segs->word[h_st].conv,stm->seg[r_st].file);
1233
+ fprintf(stderr," synchronized\n");
1234
+ return((SCORES *)0);
1235
+ }
1236
+
1237
+ /* write out the words in the STM file */
1238
+ dump_STM_words(stm,r_st,r_end+((r_end==stm->num)?-1:0),refwords);
1239
+ dump_WTOKE_words(hyp_segs, h_st, h_end, hypwords);
1240
+
1241
+ if ((fp_diff = readpipe (DIFF_PROGRAM, "-y",refwords, hypwords, NULL)) == NULL){
1242
+ fprintf(stderr,"Error: Execution of 'diff' failed\n");
1243
+ exit(1);
1244
+ }
1245
+
1246
+ for (r=r_st; r<=r_end + ((r_end==stm->num)?-1:0); r++){
1247
+ path = PATH_alloc(100);
1248
+ path->num = 0;
1249
+
1250
+ /* for each reference word, located it's matching diff output*/
1251
+ ctext = tokenize_TEXT_first_alt(stm->seg[r].text,
1252
+ (TEXT*)" \t\n");
1253
+ while (ctext != NULL){
1254
+ do {
1255
+ if (TEXT_ensure_fgets(&diff_out,&diff_out_len,fp_diff)
1256
+ == NULL)
1257
+ *diff_out = '\0';
1258
+ if (feof(fp_diff)) break;
1259
+ process_diff_line(diff_out,path,&firsttoken);
1260
+ } while (!feof(fp_diff) &&
1261
+ ((TEXT_strcmp(firsttoken,ctext) != 0) ||
1262
+ r== r_end + (r_end==stm->num)?-1:0));
1263
+ ctext = tokenize_TEXT_first_alt(NULL,(TEXT *)" \t\n");
1264
+ }
1265
+ spkr = SCORES_get_grp(scor,(char *)stm->seg[r].spkr);
1266
+ PATH_add_utt_id(path,rsprintf("(%s-%03d)",stm->seg[r].spkr,
1267
+ scor->grp[spkr].nsent));
1268
+ PATH_set_sequence(path);
1269
+ PATH_add_label(path,(char *)stm->seg[r].labels);
1270
+ PATH_add_file(path,(char *)stm->seg[r].chan);
1271
+ PATH_add_channel(path,(char *)stm->seg[r].chan);
1272
+ if (case_sense) BF_SET(path->attrib,PA_CASE_SENSE);
1273
+ add_PATH_score(scor,path,spkr, keep_path);
1274
+
1275
+ if (feedback >= 2){
1276
+ printf("\n");
1277
+ PATH_print(path,stdout,199);
1278
+ printf("\n");
1279
+ }
1280
+ if (!keep_path) PATH_free(path);
1281
+ }
1282
+ fclose(fp_diff);
1283
+
1284
+
1285
+ stm->s = r_end+1;
1286
+ } /* for each channel */
1287
+
1288
+ /* increment the start pointers */
1289
+ hyp_segs->s = hyp_end_chan2+1;
1290
+ stm->s = ref_end_chan2+1;
1291
+ } while (hyp_segs->s <= hyp_segs->n);
1292
+
1293
+ fclose(fp_hyp);
1294
+ fclose(fp_ref);
1295
+
1296
+ unlink(refwords);
1297
+ unlink(hypwords);
1298
+ free_singarr(diff_out,TEXT);
1299
+
1300
+ free_mark_file(hyp_segs);
1301
+ free_STM(stm);
1302
+
1303
+ return(scor);
1304
+ }
1305
+
1306
+ void convert_text_to_word_list(char *file, char *words,int case_sense){
1307
+ FILE *fp, *fp_out;
1308
+ TEXT *buf, *ctext;
1309
+ int buf_len=100;
1310
+
1311
+ if ((fp=fopen(file,"r")) == NULL){
1312
+ fprintf(stderr,"Error: Unable to open input STM file '%s'\n",file);
1313
+ exit(1);
1314
+ }
1315
+
1316
+ if ((fp_out=fopen(words,"w")) == NULL){
1317
+ fprintf(stderr,"Error: Unable to open STM word file '%s'\n",words);
1318
+ exit(1);
1319
+ }
1320
+
1321
+ alloc_singZ(buf,buf_len,TEXT,'\0');
1322
+
1323
+ /* for each stm, load the aligned text and create a path as before */
1324
+ while (!feof(fp)){
1325
+ /* read the next ref line */
1326
+ *buf = '\0';
1327
+ while (!feof(fp) && (TEXT_is_comment(buf) ||
1328
+ TEXT_is_comment_info(buf) ||
1329
+ TEXT_is_empty(buf)))
1330
+ if (TEXT_ensure_fgets(&buf,&buf_len,fp) == NULL)
1331
+ *buf = '\0';
1332
+ if (*buf == '\0' && feof(fp)) break;
1333
+ if (!case_sense) TEXT_str_case_change_with_mem_expand(&buf, &buf_len, 1);
1334
+
1335
+ /* for each reference word, located it's matching diff output */
1336
+ ctext = TEXT_strtok(buf,(TEXT *)" \t\n");
1337
+ while (ctext != NULL){
1338
+ fprintf(fp_out,"%s\n",ctext);
1339
+ ctext = TEXT_strtok(NULL,(TEXT *)" \t\n");
1340
+ }
1341
+ }
1342
+ fclose(fp);
1343
+ fclose(fp_out);
1344
+ free_singarr(buf,TEXT);
1345
+ }
1346
+
1347
+ SCORES *align_text_to_stm(char *ref_file, char *hyp_file, char *set_title, int keep_path, int case_sense, int feedback, enum id_types idt){
1348
+ /* char *proc="align_text_to_stm"; */
1349
+ FILE *fp_ref;
1350
+ PATH *path;
1351
+ SCORES *scor;
1352
+ int spkr, num_ref;
1353
+ char refwords[100], hypwords[100];
1354
+ TEXT *diff_out, *ref_buf, *firsttoken, *ctext;
1355
+ int diff_out_len=100, ref_buf_len=100;
1356
+ FILE *fp_diff;
1357
+ STM_SEG ref_seg;
1358
+
1359
+ /* allocate memory */
1360
+ scor = SCORES_init(set_title,20);
1361
+ scor->ref_fname = (char *)TEXT_strdup((TEXT *)ref_file);
1362
+ scor->hyp_fname = (char *)TEXT_strdup((TEXT *)hyp_file);
1363
+ scor->creation_date = get_date();
1364
+
1365
+ alloc_singZ(diff_out,diff_out_len,TEXT,'\0');
1366
+ alloc_singZ(ref_buf,ref_buf_len,TEXT,'\0');
1367
+
1368
+ set_temp_files(refwords, hypwords);
1369
+
1370
+ /* stm to word texts */
1371
+ convert_stm_to_word_list(ref_file,refwords,case_sense,&num_ref);
1372
+
1373
+ /* text to word separeted texts */
1374
+ convert_text_to_word_list(hyp_file,hypwords,case_sense);
1375
+
1376
+ /* start up diff */
1377
+ if ((fp_diff = readpipe (DIFF_PROGRAM,"-y",refwords, hypwords, NULL)) ==
1378
+ NULL){
1379
+ fprintf(stderr,"Error: Execution of 'diff' failed\n");
1380
+ exit(1);
1381
+ }
1382
+
1383
+ /* again, open the input reference file */
1384
+ if ((fp_ref = fopen(ref_file,"r")) == NULL){
1385
+ fprintf(stderr,"Can't open input reference file %s\n",ref_file);
1386
+ exit(1);
1387
+ }
1388
+
1389
+ /* for each stm, load the aligned text and create a path as before */
1390
+ while (!feof(fp_ref)){
1391
+ /* read the next ref line */
1392
+ read_stm_line(&ref_buf,&ref_buf_len,fp_ref);
1393
+ if (feof(fp_ref)) break;
1394
+
1395
+ /* parse the reference transcript */
1396
+ parse_stm_line(&ref_seg, &ref_buf, &ref_buf_len, case_sense, 0);
1397
+ num_ref --;
1398
+
1399
+ /* allocate a path structure */
1400
+ path = PATH_alloc(100); path->num = 0;
1401
+
1402
+ /* for each reference word, located it's matching diff output */
1403
+ ctext = tokenize_TEXT_first_alt(ref_seg.text,(TEXT *)" \t\n");
1404
+ while (ctext != NULL){
1405
+ do {
1406
+ if (TEXT_ensure_fgets(&diff_out,&diff_out_len,fp_diff) == NULL)
1407
+ *diff_out = '\0';
1408
+ if (feof(fp_diff)) break;
1409
+ process_diff_line(diff_out,path,&firsttoken);
1410
+ } while (!feof(fp_diff) &&
1411
+ ((TEXT_strcmp(firsttoken,ctext) != 0) || num_ref==0));
1412
+ ctext = tokenize_TEXT_first_alt(NULL,(TEXT *)" \t\n");
1413
+ }
1414
+
1415
+ spkr = SCORES_get_grp(scor,(char *)ref_seg.spkr);
1416
+ PATH_add_utt_id(path,rsprintf("(%s-%03d)",ref_seg.spkr,
1417
+ scor->grp[spkr].num_path));
1418
+ PATH_set_sequence(path);
1419
+ PATH_add_label(path,(char *)ref_seg.labels);
1420
+ PATH_add_file(path,(char *)ref_seg.file);
1421
+ PATH_add_channel(path,(char *)ref_seg.chan);
1422
+ if (case_sense) BF_SET(path->attrib,PA_CASE_SENSE);
1423
+ add_PATH_score(scor,path,spkr, keep_path);
1424
+
1425
+ if (feedback >= 2){
1426
+ printf("\n");
1427
+ PATH_print(path,stdout,199);
1428
+ printf("\n");
1429
+ }
1430
+ if (!keep_path) PATH_free(path);
1431
+ free_STM_SEG(&ref_seg);
1432
+ }
1433
+ fclose(fp_diff);
1434
+ fclose(fp_ref);
1435
+
1436
+ free_singarr(diff_out,TEXT);
1437
+ free_singarr(ref_buf,TEXT);
1438
+
1439
+ unlink(refwords);
1440
+ unlink(hypwords);
1441
+
1442
+ return(scor);
1443
+ }
SCTK/src/sclite/align.o ADDED
Binary file (48.7 kB). View file
 
SCTK/src/sclite/anovar.c ADDED
@@ -0,0 +1,485 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**********************************************************************/
2
+ /* */
3
+ /* FILE: anovar.c */
4
+ /* WRITTEN BY: Jonathan G. Fiscus */
5
+ /* DATE: April 14 1989 */
6
+ /* NATIONAL INSTITUTE OF STANDARDS AND TECHNOLOGY */
7
+ /* SPEECH RECOGNITION GROUP */
8
+ /* */
9
+ /* USAGE: This uses the rank structure to perform */
10
+ /* a Friedman two-way analysis of variance */
11
+ /* by ranks and generates a report. */
12
+ /* */
13
+ /* SOURCE:Applied Non Parametric Statistics by Daniel */
14
+ /* */
15
+ /**********************************************************************/
16
+
17
+ #include "sctk.h"
18
+
19
+ #define FRI_TITLE "Friedman Two-way Analysis of Variance by Ranks"
20
+ #define RANK_TITLEA "COMPARISON MATRIX: Comparing All Systems"
21
+ #define RANK_TITLEB "COMPARISON MATRIX: Comparing All Speakers"
22
+ #define RANK_TITLE_1 "Using a Multiple Comparison Test"
23
+ #define ADJUST_THRESH 0.50000
24
+ #define MULTI_COMP_ALPHA 0.05
25
+
26
+
27
+ static int analyze_rank_sum(RANK *, int, int, double *, int, int, FILE *);
28
+ static void print_result_of_analyze_rank_sum(int, double, double, char *,FILE *);
29
+ static double dsum_sqr(double *, int);
30
+ static double calc_adjust_for_trt(RANK *);
31
+ static double calc_adjust_for_blks(RANK *);
32
+ static void do_multi_comp_for_anovar(int, int, char **, double *, double *, char *, int *, int **, int, FILE *);
33
+ static void calc_stat_ranks(int, int, int **, double*);
34
+ static double calc_comp_value(int, int);
35
+ static void print_ANOVAR_comp_matrix(int, int **, char **, char *, int *, FILE *);
36
+
37
+ /****************************************************************/
38
+ /* main procedure to perform a two-way analysis of variance by*/
39
+ /* ranks. first the sum of the treatment and block ranks */
40
+ /* are summed then if there is a difference between at least */
41
+ /* one of the blocks or treatments, then a multiple comparison*/
42
+ /* is performed */
43
+ /****************************************************************/
44
+ void compute_anovar(RANK *rank, int verbose, int report, int ***out_sys_winner, char *outroot, int feedback, double ***out_conf)
45
+ {
46
+ double *sum_trt_rank, *sum_blk_rank;
47
+ char pad[FULL_SCREEN];
48
+ int i,j, **trt_winner, **blk_winner;
49
+ double **conf;
50
+ FILE *fp = stdout;
51
+
52
+ if (report || verbose){
53
+ char *f = rsprintf("%s.anovar",outroot);
54
+ if ((fp=(strcmp(outroot,"-") == 0) ? stdout : fopen(f,"w")) ==
55
+ (FILE *)0){
56
+ fprintf(stderr,"Warning: Open of %s for write failed. "
57
+ "Using stdout instead.\n",f);
58
+ fp = stdout;
59
+ } else
60
+ if (feedback >= 1) printf(" Output written to '%s'\n",f);
61
+ }
62
+
63
+ alloc_2dimZ(conf,rank->n_trt,rank->n_trt,double,0.0);
64
+ alloc_2dimZ(trt_winner,rank->n_trt,rank->n_trt,int,NO_DIFF);
65
+ alloc_2dimZ(blk_winner,rank->n_blk,rank->n_blk,int,NO_DIFF);
66
+ *out_sys_winner = trt_winner;
67
+ *out_conf = conf;
68
+
69
+ alloc_singZ(sum_trt_rank,rnk_trt(rank),double,0.0);
70
+ alloc_singZ(sum_blk_rank,rnk_blks(rank),double,0.0);
71
+
72
+ /* sum the ranks */
73
+ for (i=0;i<rnk_blks(rank);i++)
74
+ for (j=0;j<rnk_trt(rank);j++){
75
+ sum_trt_rank[j] += Vrnk_t_rank(rank,i,j);
76
+ sum_blk_rank[i] += Vrnk_b_rank(rank,i,j);
77
+ }
78
+
79
+ if (verbose){
80
+ set_pad(pad,FRI_TITLE, FULL_SCREEN);
81
+ fprintf(fp,"\n\n\n%s%s\n",pad,FRI_TITLE);
82
+ fprintf(fp,"%s----------------------------------------------\n\n",pad);
83
+ set_pad_cent_n(pad,SCREEN_WIDTH, FULL_SCREEN);
84
+ fprintf(fp,"%s\tHo: Testing the hypothesis that all recognizers are the same",
85
+ pad);
86
+ }
87
+ /* if at least one difference, do multiple comparison */
88
+ if (analyze_rank_sum(rank,rnk_trt(rank),rnk_blks(rank),
89
+ sum_trt_rank,
90
+ FOR_TREATMENTS,verbose,fp) == TEST_DIFF)
91
+ clear_2dim(trt_winner,rank->n_trt,rank->n_trt,NO_DIFF);
92
+ do_multi_comp_for_anovar(rnk_trt(rank),rnk_blks(rank),
93
+ rnk_t_name(rank),sum_trt_rank,
94
+ ovr_t_rank(rank),RANK_TITLEA,
95
+ srt_t_rank(rank),trt_winner,verbose,fp);
96
+ if (verbose) form_feed(fp);
97
+
98
+ if (verbose){
99
+ set_pad(pad,FRI_TITLE, FULL_SCREEN);
100
+ fprintf(fp,"\n\n\n%s%s\n",pad,FRI_TITLE);
101
+ fprintf(fp,"%s----------------------------------------------\n\n",pad);
102
+ set_pad_cent_n(pad,SCREEN_WIDTH, FULL_SCREEN);
103
+ fprintf(fp,"%s\tHo: Testing the hypothesis that all speakers are the same",
104
+ pad);
105
+ }
106
+ /* if at least one difference, do multiple comparison */
107
+ if (analyze_rank_sum(rank,rnk_blks(rank),rnk_trt(rank),sum_blk_rank,
108
+ FOR_BLOCKS,verbose,fp) == TEST_DIFF)
109
+ clear_2dim(blk_winner,rank->n_blk,rank->n_blk,NO_DIFF);
110
+ do_multi_comp_for_anovar(rnk_blks(rank),rnk_trt(rank),
111
+ rnk_b_name(rank),sum_blk_rank,
112
+ ovr_b_rank(rank),RANK_TITLEB,
113
+ srt_b_rank(rank),blk_winner, verbose,fp);
114
+ if (verbose && (fp == stdout)) form_feed(fp);
115
+ free_2dimarr(blk_winner,rank->n_blk,int);
116
+ free_singarr(sum_trt_rank,double);
117
+ free_singarr(sum_blk_rank,double);
118
+ if (fp != stdout) fclose(fp);
119
+ }
120
+
121
+ /*****************************************************************/
122
+ /* X2_r formula: */
123
+ /* k */
124
+ /* 12 --. 2 */
125
+ /* ------- * \ R - 3b(t+1) */
126
+ /* bt(t+1) / j */
127
+ /* --' */
128
+ /* j = 1 */
129
+ /* */
130
+ /* b = num_blk */
131
+ /* t = num_trt */
132
+ /* R = Sum of the ranks for that column */
133
+ /* */
134
+ /* this is the initial test to see if the treatment or ranks */
135
+ /* are different */
136
+ /*****************************************************************/
137
+ static int analyze_rank_sum(RANK *rank, int trt_num, int blk_num, double *sum_arr, int orient, int verbose,FILE *fp)
138
+ {
139
+ int df;
140
+ double X2_r, adjust;
141
+ char *subject_blk = "speaker";
142
+ char *subject_trt = "recognition system";
143
+
144
+ /* calculate the test statistic */
145
+ df = trt_num - 2; /* #trt is one based so subtract 2 */
146
+ /* make sure df isn't negative */;
147
+ if (df < 0) df = 0;
148
+ /* make sure df isn't greater than MAX_DF */
149
+ if (df > MAX_DF) df = MAX_DF;
150
+
151
+ X2_r = (12.00000 /
152
+ (double)(blk_num*trt_num*(trt_num+1))) *
153
+ (dsum_sqr(sum_arr,trt_num)) -
154
+ 3.00000 * (double)blk_num * (double)(trt_num+1);
155
+ if (orient == FOR_TREATMENTS)
156
+ adjust = calc_adjust_for_trt(rank);
157
+ else
158
+ adjust = calc_adjust_for_blks(rank);
159
+
160
+ /* if two identical systems are entered, adjust will be 0.0 and core*/
161
+ /* dump. this avoids this */
162
+ if (adjust == 0.0)
163
+ X2_r = 0.0;
164
+ else
165
+ X2_r /= adjust;
166
+
167
+ if (verbose) {
168
+ if (orient == FOR_TREATMENTS)
169
+ print_result_of_analyze_rank_sum(df, X2_r, adjust, subject_trt,fp);
170
+ else
171
+ print_result_of_analyze_rank_sum(df, X2_r, adjust, subject_blk,fp);
172
+ }
173
+ /* return the result */
174
+ if (X2_r > X2.df[df].level[GEN_X2_PER])
175
+ return(TEST_DIFF);
176
+ else
177
+ return(NO_DIFF);
178
+ }
179
+
180
+ /*****************************************************************/
181
+ /* print to stdout the results of the rank_sum test */
182
+ /*****************************************************************/
183
+ static void print_result_of_analyze_rank_sum(int df, double X2_r, double adjust, char *subject, FILE *fp)
184
+ {
185
+ char pad[FULL_SCREEN];
186
+ int i;
187
+
188
+ set_pad_cent_n(pad,SCREEN_WIDTH, FULL_SCREEN);
189
+ fprintf(fp,"\n\n\n%s%35sReject if\n",pad,"");
190
+ fprintf(fp,"%s%26sX2_r > X2 of %s %s (%2.3f)\n", pad, "",
191
+ X2_pct_str(GEN_X2_PER),
192
+ X2_df_str(df),
193
+ X2_score(df,GEN_X2_PER));
194
+ fprintf(fp,"\n");
195
+ fprintf(fp,"%s%26sadjustment = %2.3f\n",pad,"",adjust);
196
+ fprintf(fp,"%s%30s X2_r = %2.3f\n",pad,"",X2_r);
197
+ if (adjust < ADJUST_THRESH){
198
+ fprintf(fp,"\n\n%s\t\t*** Warning: ties adjustment may have severely\n",
199
+ pad);
200
+ fprintf(fp,"%s\t\t exagerated the X2_r value\n\n",pad);
201
+ }
202
+ fprintf(fp,"%sANALYSIS:\n%s--------\n",pad,pad);
203
+ if (X2_r > X2_score(df,GEN_X2_PER)){
204
+ fprintf(fp,"%s\tThe test statistic X2_r shows, with %s confidence, that at\n"
205
+ ,pad,X2.neg_per_str[GEN_X2_PER]),
206
+ fprintf(fp,"%s\tleast one %s is significantly different.\n",pad,subject);
207
+ fprintf(fp,"\n");
208
+ fprintf(fp,"%s\tFurther, the probablity of there being a difference is\n",
209
+ pad);
210
+ for (i=GEN_X2_PER;i<MAX_X2_PER;i++)
211
+ if (X2_r < X2_score(df,i+1))
212
+ break;
213
+ if (i==MAX_X2_PER)
214
+ fprintf(fp,"%s\tgreater that %s.\n",pad,X2_neg_pct_str(i));
215
+ else
216
+ fprintf(fp,"%s\tbetween %s to %s.\n",pad,X2_neg_pct_str(i),
217
+ X2_neg_pct_str(i+1));
218
+ fprintf(fp,"\n\n");
219
+ }
220
+ else{
221
+ fprintf(fp,"%s\tThe test statistic X2_r shows that at the %s confidence\n"
222
+ ,pad,X2_neg_pct_str(GEN_X2_PER)),
223
+ fprintf(fp,"%s\tinterval, the %ss are not significantly\n",pad,subject);
224
+ fprintf(fp,"%s\tdifferent.\n\n",pad);
225
+ fprintf(fp,"%s\tFurther, the probablity of there being a difference is\n"
226
+ ,pad);
227
+ for (i=GEN_X2_PER;i>MIN_X2_PER;i--)
228
+ if (X2_r > X2_score(df,i-1))
229
+ break;
230
+ if (i==MIN_X2_PER)
231
+ fprintf(fp,"%s\tless than %s.\n",pad,X2_neg_pct_str(i));
232
+ else
233
+ fprintf(fp,"%s\tbetween %s to %s.\n",pad,X2_neg_pct_str(i-1),
234
+ X2_neg_pct_str(i));
235
+ fprintf(fp,"\n\n");
236
+ }
237
+ }
238
+
239
+ /********************************************************************/
240
+ /* return the doubleing point value of the sum of the squares */
241
+ /********************************************************************/
242
+ static double dsum_sqr(double *arr, int len)
243
+ {
244
+ int i;
245
+ double tot=0.000000;
246
+
247
+ for (i=0;i<len;i++)
248
+ tot += (arr[i]*arr[i]);
249
+ return(tot);
250
+ }
251
+
252
+ /********************************************************************/
253
+ /* Ties adjustments */
254
+ /* b */
255
+ /* --. */
256
+ /* 1 - \ T */
257
+ /* / i */
258
+ /* --' */
259
+ /* ----------- */
260
+ /* 2 */
261
+ /* bt(t -1) */
262
+ /* */
263
+ /* 3 */
264
+ /* T = Sum t - Sum t where t = num ties in ith block */
265
+ /* i i i */
266
+ /* */
267
+ /* to adjust for ties, the test statistic must be taken down */
268
+ /* by a certain factor, this function returns it */
269
+ /********************************************************************/
270
+ static double calc_adjust_for_trt(RANK *rank)
271
+ {
272
+ double *sort_arr;
273
+ int sort_num, *sort_count, i, j, sum_T=0;
274
+
275
+ alloc_singarr(sort_arr,rnk_trt(rank),double);
276
+ alloc_singarr(sort_count,rnk_trt(rank),int);
277
+
278
+ /* find the ties ans sum Ti */
279
+ for (i=0;i<rnk_blks(rank);i++){
280
+ for (j=0;j<rnk_trt(rank); j++){
281
+ sort_arr[j]=0.0;
282
+ sort_count[j]=0;
283
+ }
284
+ for (j=0;j<rnk_trt(rank); j++){
285
+ sort_num = 0;
286
+ while ((sort_arr[sort_num] != 0.0) &&
287
+ (Vrnk_t_rank(rank,i,j) != sort_arr[sort_num]))
288
+ sort_num++;
289
+ sort_arr[sort_num] = Vrnk_t_rank(rank,i,j);
290
+ sort_count[sort_num]++;
291
+ }
292
+ for (j=0;j<rnk_trt(rank); j++)
293
+ if (sort_count[j] > 0)
294
+ sum_T += (sort_count[j] * sort_count[j] * sort_count[j])
295
+ - sort_count[j];
296
+ }
297
+ free_singarr(sort_arr,double);
298
+ free_singarr(sort_count,int);
299
+
300
+ /* return the adjustment number */
301
+ return( 1.000000 - (sum_T/
302
+ (double)(rnk_blks(rank)*
303
+ rnk_trt(rank)*
304
+ ((rnk_trt(rank) * rnk_trt(rank)) - 1))));
305
+ }
306
+
307
+ /********************************************************************/
308
+ /* see calc_adjust_for_trt but substitute B for t */
309
+ /********************************************************************/
310
+ static double calc_adjust_for_blks(RANK *rank)
311
+ {
312
+ double *sort_arr;
313
+ int sort_num, *sort_count, i, j, sum_T=0;
314
+
315
+ alloc_singarr(sort_arr,rnk_blks(rank),double);
316
+ alloc_singarr(sort_count,rnk_blks(rank),int);
317
+
318
+ /* find the ties ans sum Ti */
319
+ for (i=0;i<rnk_trt(rank);i++){
320
+ for (j=0;j<rnk_blks(rank); j++){
321
+ sort_arr[j]=0.0;
322
+ sort_count[j]=0;
323
+ }
324
+ for (j=0;j<rnk_blks(rank); j++){
325
+ sort_num = 0;
326
+ while ((sort_arr[sort_num] != 0.0) &&
327
+ (Vrnk_b_rank(rank,j,i) != sort_arr[sort_num]))
328
+ sort_num++;
329
+ sort_arr[sort_num] = Vrnk_b_rank(rank,j,i);
330
+ sort_count[sort_num]++;
331
+ }
332
+ for (j=0;j<rnk_trt(rank); j++)
333
+ if (sort_count[j] > 0)
334
+ sum_T += (sort_count[j] * sort_count[j] * sort_count[j])
335
+ - sort_count[j];
336
+ }
337
+ free_singarr(sort_arr,double);
338
+ free_singarr(sort_count,int);
339
+ /* return the adjustment number */
340
+ return( 1.000000 - (sum_T/
341
+ (double)(rnk_trt(rank)*
342
+ rnk_blks(rank)*
343
+ ((rnk_blks(rank) * rnk_blks(rank)) - 1))));
344
+ }
345
+
346
+ /********************************************************************/
347
+ /* for the treatments, calculate and do the MULTIPLE comparison */
348
+ /* print everything out if requested */
349
+ /********************************************************************/
350
+ static void do_multi_comp_for_anovar(int trt_num, int blk_num, char **trt_names, double *sum_arr, double *ovr_rank_arr, char *title, int *srt_ptr, int **stat_sum, int verbose, FILE *fp)
351
+ {
352
+ calc_stat_ranks(trt_num,blk_num,stat_sum,sum_arr);
353
+
354
+ if (verbose)
355
+ print_ANOVAR_comp_matrix(trt_num,stat_sum,trt_names,title,srt_ptr,fp);
356
+ }
357
+
358
+ /*********************************************************************/
359
+ /* Multiple comparison test to rank the systems */
360
+ /* ________ */
361
+ /* / bt(t+1) */
362
+ /* | R - R | >= z / -------- */
363
+ /* j i V 6 */
364
+ /* */
365
+ /* R = the Sum of the nth column ranks */
366
+ /* z = Z score the alpha = 0.05 */
367
+ /* ---- */
368
+ /* t(t-1) */
369
+ /* */
370
+ /* go through all possible comparisons and rank the treatments for */
371
+ /* according to the number of treatments beaten or beaten by */
372
+ /* */
373
+ /*********************************************************************/
374
+ static void calc_stat_ranks(int trt_num, int blk_num, int **stat_sum, double *sum_arr)
375
+ {
376
+ int comp1, comp2, result;
377
+ double Zcomp_value, compare_value;
378
+ double sqr_root;
379
+
380
+ /* calculate the comparison value for the confidence interval */
381
+ Zcomp_value = calc_comp_value(trt_num,blk_num);
382
+ sqr_root = sqrt(blk_num * trt_num * (trt_num - 1) / 6.000000);
383
+ compare_value = (double)Zcomp_value * (double)sqr_root;
384
+
385
+ /* go through the comparison and build an array to rank */
386
+ for (comp1=0; comp1 <(trt_num-1); comp1++)
387
+ for (comp2=comp1+1; comp2<(trt_num); comp2++){
388
+ if (fabs(sum_arr[comp1] - sum_arr[comp2]) >= compare_value)
389
+ if (sum_arr[comp1] > sum_arr[comp2])
390
+ result = 1;
391
+ else
392
+ result = -1;
393
+ else
394
+ result = 0;
395
+ stat_sum[comp1][comp2] += result;
396
+ stat_sum[comp2][comp1] += result * (-1);
397
+ }
398
+ }
399
+
400
+ /*********************************************************************/
401
+ /* Given the alpha, find the closest approximate Z index to that */
402
+ /* percentage */
403
+ /*********************************************************************/
404
+ static double calc_comp_value(int trt_num, int blk_num)
405
+ {
406
+ double Z_area;
407
+ int i;
408
+
409
+ Z_area = MULTI_COMP_ALPHA / (double)(trt_num * (trt_num-1));
410
+
411
+ if (Z_area < Z_exter(Z1tail,MAX_Z_PER))
412
+ return(Z_score(Z1tail,MAX_Z_PER));
413
+
414
+ for (i=MAX_Z_PER+1; i< MIN_Z_PER ; i++)
415
+ if (Z_area < Z_exter(Z1tail,i))
416
+ return(Z_score(Z1tail,i));
417
+
418
+ return(Z_score(Z1tail,MIN_Z_PER));
419
+ }
420
+
421
+
422
+ static void print_ANOVAR_comp_matrix(int trt_num, int **stat_sum, char **trt_names, char *title, int *srt_ptr, FILE *fp)
423
+ {
424
+ char pad[FULL_SCREEN],name_format[50],*hyphens="--------------------";
425
+ char *spaces=" ";
426
+ int t, t2;
427
+ int max_trt_name_len=4, hy_l=20;
428
+
429
+ set_pad(pad,title, FULL_SCREEN);
430
+ fprintf(fp,"\n\n%s%s\n",pad,title);
431
+ set_pad(pad,RANK_TITLE_1, FULL_SCREEN);
432
+ fprintf(fp,"%s%s\n\n\n\n",pad,RANK_TITLE_1);
433
+
434
+ for (t=0; t<trt_num; t++)
435
+ if (max_trt_name_len < strlen(trt_names[t]))
436
+ max_trt_name_len = strlen(trt_names[t]);
437
+ set_pad_cent_n(pad,(trt_num+1) * (max_trt_name_len+2+1), FULL_SCREEN);
438
+ sprintf(name_format,"| %%-%ds ",max_trt_name_len);
439
+
440
+ /* first line */
441
+ fprintf(fp,"%s|%s",pad,(hyphens+(hy_l-(max_trt_name_len+2))));
442
+ for (t=0; t<trt_num; t++)
443
+ fprintf(fp,"%s",(hyphens+(hy_l-(max_trt_name_len+3))));
444
+ fprintf(fp,"|\n");
445
+
446
+ /* systems on top */
447
+ fprintf(fp,"%s|%s",pad,(spaces+(hy_l-(max_trt_name_len+2))));
448
+ for (t=0; t<trt_num; t++)
449
+ fprintf(fp,name_format,trt_names[srt_ptr[t]]);
450
+ fprintf(fp,"|\n");
451
+
452
+ /* separation line */
453
+ fprintf(fp,"%s|%s+",pad,(hyphens+(hy_l-(max_trt_name_len+2))));
454
+ for (t=0; t<trt_num-1; t++)
455
+ fprintf(fp,"%s",(hyphens+(hy_l-(max_trt_name_len+3))));
456
+ fprintf(fp,"%s|\n",(hyphens+(hy_l-(max_trt_name_len+2))));
457
+
458
+ /* systems */
459
+ for (t=0; t<trt_num; t++){
460
+ fprintf(fp,"%s",pad);
461
+ fprintf(fp,name_format,trt_names[srt_ptr[t]]);
462
+ for (t2=0; t2<trt_num; t2++){
463
+ if (t < t2)
464
+ switch (stat_sum[srt_ptr[t]][srt_ptr[t2]]) {
465
+ case -1: fprintf(fp,name_format,trt_names[srt_ptr[t]]);
466
+ break;
467
+ case 1: fprintf(fp,name_format,trt_names[srt_ptr[t2]]);
468
+ break;
469
+ default: fprintf(fp,name_format,"same");
470
+ break;
471
+ }
472
+ else
473
+ fprintf(fp,name_format,"");
474
+ }
475
+ fprintf(fp,"|\n");
476
+ }
477
+
478
+ /* last line */
479
+ fprintf(fp,"%s|%s",pad,(hyphens+(hy_l-(max_trt_name_len+2))));
480
+ for (t=0; t<trt_num; t++)
481
+ fprintf(fp,"%s",(hyphens+(hy_l-(max_trt_name_len+3))));
482
+ fprintf(fp,"|\n");
483
+ }
484
+
485
+
SCTK/src/sclite/arcseq1.c ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* file arcseq1.c */
2
+
3
+ #include "sctk.h"
4
+
5
+ boolean arcs_equal(ARC *arc1, ARC *arc2)
6
+ /***************************************************/
7
+ /* Determines if two arcs of a network are equal. */
8
+ /***************************************************/
9
+ {if ((arc1->from_node == arc2->from_node) &&
10
+ /* (streq(arc1->symbol,arc2->symbol)) && */
11
+ (arc1->to_node == arc2->to_node)) return T;
12
+ else return F;
13
+ }
SCTK/src/sclite/arcseq1.o ADDED
Binary file (1.24 kB). View file
 
SCTK/src/sclite/config.in ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ dnl Process this file with autoconf to produce a configure script.
2
+ AC_INIT(sclite.c)
3
+
4
+ dnl Checks for programs.
5
+ AC_PROG_CC
6
+ dnl AC_PROG_INSTALL
7
+ AC_PROG_MAKE_SET
8
+
9
+ dnl Checks for libraries.
10
+ dnl Replace `main' with a function in -lm:
11
+ AC_CHECK_LIB(m, main)
12
+
13
+ dnl Checks for header files.
14
+ AC_HEADER_STDC
15
+ AC_CHECK_HEADERS(unistd.h)
16
+
17
+ dnl If gcc is used, check the system. If it's any of the below,
18
+ dnl add OPTIONS to CFLAGS
19
+ if test "$CC" = "cc" ; then
20
+ echo "Setting default CFLAGS for Native cc"
21
+ case "`uname -s`" in
22
+ OSF1) CFLAGS="$CFLAGS -std1"; export CFLAGS;;
23
+ HP-UX) CFLAGS="$CFLAGS -Ae"; export CFLAGS;;
24
+ esac
25
+ fi
26
+
27
+ dnl Checks for typedefs, structures, and compiler characteristics.
28
+ AC_C_CONST
29
+ AC_TYPE_SIZE_T
30
+
31
+ dnl Checks for library functions.
32
+ dnl AC_FUNC_VPRINTF
33
+ dnl AC_CHECK_FUNCS(strdup)
34
+ dnl AC_CHECK_FUNC(readpipe)
35
+
36
+ AC_PATH_PROGS(INSTALL, install cp copy)
37
+
38
+ echo ""
39
+ echo "!!!!!!!!!!!!! USER INFORMATION NEEDED !!!!!!!!!!!!!"
40
+ echo ""
41
+ echo "Sclite has the ability to use GNU's 'diff' program as means to"
42
+ echo "align reference and hypothesis strings. Currently, no evaluations"
43
+ echo "have used GNU-DIFF for alignments, so it may be unnecessary for"
44
+ echo "you to enable its use. Also, some versions of GNU's diff, V2.8.1,"
45
+ echo "will not work with GB encoded Mandarin characters and test6 of the"
46
+ echo "test suite will fail."
47
+ echo ""
48
+ echo " Do you want to enable alignments via GNU's 'diff'? yes or no"
49
+ echo ""
50
+ ans=""
51
+ while test "$ans" = "" ; do
52
+ read ans
53
+ ans=`echo $ans | tr 'A-Z' 'a-z'`
54
+ if test "$ans" = "no" ; then
55
+ echo "Disabling GNU-DIFF alignments"
56
+ elif test "$ans" = "yes" ; then
57
+ echo "Enabling GNU-DIFF alignments"
58
+ else
59
+ echo "Error: You must respond either yes or no"
60
+ ans=""
61
+ fi
62
+ done
63
+
64
+ CFLAGS_BEFORE_DIFF=$CFLAGS
65
+ if test "$ans" = "yes" ; then
66
+ AC_PATH_PROGS(DIFF, gnudiff diffgnu gdiff diff)
67
+ case "$DIFF" in
68
+ *gdiff)
69
+ # Carefully avoid gdiff for X as found on SGI systems.
70
+ DISPLAY= gdiff /dev/null /dev/null > /dev/null 2>&1 || DIFF=""
71
+ if test -z "$DIFF" ; then
72
+ echo " Not using $DIFF, it's an X window executable"
73
+ AC_PATH_PROGS(NDIFF, diff)
74
+ DIFF=$NDIFF
75
+ fi
76
+ ;;
77
+ esac
78
+ if test -z "$DIFF" ; then
79
+ echo "Error: Unable to locate 'diff'"
80
+ exit 1
81
+ fi
82
+ echo " Making sure diff supports '-y'"
83
+ if test ! -z "`$DIFF -y /dev/null /dev/null 2>&1`" ; then
84
+ echo "Error: $DIFF does not support '-y'. Install GNU's diff"
85
+ exit 1
86
+ fi
87
+ CFLAGS="$CFLAGS -DDIFF_EXE=\\\"\$(GNUDIFF)\\\""
88
+ else
89
+ DIFF=""
90
+ fi
91
+
92
+ echo ""
93
+ echo "!!!!!!!!!!!!! USER INFORMATION NEEDED !!!!!!!!!!!!!"
94
+ echo ""
95
+ echo "In support of the LVCSR/HUB-5 evaluations, a newly defined DP"
96
+ echo "alignment cost function has been incorporated into SCTK. The cost"
97
+ echo "function is defined to be a function of language model probabilities."
98
+ echo "In order to compute the LM probabilities, the CMU-Cambridge SLM"
99
+ echo "Toolkit - V2 has been included in SCTK. The compilation including"
100
+ echo "the SLM toolkit is optional, depending on your needs."
101
+ echo ""
102
+ echo " Do you want to compile in the CMU-Cambridge SLM toolkit? yes or no"
103
+ echo ""
104
+ ans=""
105
+ SLM_DEFS=""
106
+ while test "$ans" = "" ; do
107
+ read ans
108
+ ans=`echo $ans | tr 'A-Z' 'a-z'`
109
+ if test "$ans" = "no" ; then
110
+ echo "Disabling Compilation of CMU-Cambridge SLM "
111
+ SLM_TARGETS=""
112
+ elif test "$ans" = "yes" ; then
113
+ echo "Enabling Compilation of CMU-Cambridge SLM "
114
+ echo " Checking for Un-expanded tar archive of SLM"
115
+ if test -f slm_v2.tar ; then
116
+ echo " Expanding tar file"
117
+ tar xf slm_v2.tar
118
+ rm slm_v2.tar
119
+ fi
120
+ echo " Checking Endian-ness for SLM toolkit"
121
+ echo 'main(){short s=1; char *b=(char *)&s; printf("%s",(*b==0)?"Big":"Little");}' > x.c
122
+ $CC $CFLAGS_BEFORE_DIFF x.c -o a.out
123
+ endian=`./a.out`
124
+ rm -f a.out x.c
125
+
126
+ if test "$endian" = "Little" ; then
127
+ SLM_DEFS="-DSLM_SWAP_BYTES"
128
+ echo " Little-endian machine"
129
+ else
130
+ echo " Big-endian machine"
131
+ fi
132
+ CFLAGS="$CFLAGS -DWITH_SLM"
133
+ SLM_TARGETS="slm_v2/lib/SLM2.a"
134
+ cat slm_v2/src/makefile.in | \
135
+ sed "s/@CC@/$CC/" | \
136
+ sed "s/@SCTK_FLAGS@/$CFLAGS_BEFORE_DIFF/" | \
137
+ sed "s/@SLM_DEFS@/$SLM_DEFS/" > slm_v2/src/makefile
138
+ else
139
+ echo "Error: You must respond either yes or no"
140
+ ans=""
141
+ fi
142
+ done
143
+
144
+ AC_SUBST(SLM_DEFS)
145
+ AC_SUBST(SLM_TARGETS)
146
+
147
+ dnl Check to see if nist.local exists. If it does, define AT_NIST.
148
+ echo "Checking installation site"
149
+ test -f nist.local && CFLAGS="$CFLAGS -DAT_NIST -DPEDANTIC -ansi -pedantic -pedantic-errors -Wall -Wstrict-prototypes -Wmissing-prototypes -DWARN_ZERO_MALLOC"
150
+
151
+ AC_OUTPUT(Makefile)
SCTK/src/sclite/ctm2ctm.c ADDED
@@ -0,0 +1,518 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "sctk.h"
2
+
3
+ int chop_WTOKE_2(WTOKE_STR1 *ref, WTOKE_STR1 *hyp, int Rstart, int Hstart, int Rendconv, int Hendconv, int max_words, int *Rret_end, int *Hret_end);
4
+
5
+
6
+ SCORES *align_ctm_to_ctm(char *hyp_file, char *ref_file, char *set_title, int feedback, int fcorr, int opt_del, int case_sense, int time_align, int left_to_right, WWL *wwl, char *lm_file){
7
+
8
+ char *proc = "align_ctm_to_ctm";
9
+ WTOKE_STR1 *hyp;
10
+ WTOKE_STR1 *ref;
11
+ FILE *fp_hyp, *fp_ref;
12
+ int hyp_conv_end, hyp_eof;
13
+ int ref_conv_end, ref_eof;
14
+ int hyp_chop_end, ref_chop_end;
15
+ int i;
16
+ PATH *path;
17
+ int ref_end_chan1, hyp_end_chan1, ref_end_chan2, hyp_end_chan2;
18
+ int ref_end, hyp_end, ref_begin, hyp_begin;
19
+ int ref_opp_end, hyp_opp_end, ref_opp_begin, hyp_opp_begin;
20
+ int dbg = TRUE;
21
+ int chunk;
22
+ char uttid[100];
23
+ int spkr;
24
+ int number_of_channels;
25
+ SCORES *scor;
26
+ NETWORK *hnet, *rnet;
27
+ int keep_path = 1;
28
+
29
+ hyp = WTOKE_STR1_init(hyp_file);
30
+ ref = WTOKE_STR1_init(ref_file);
31
+
32
+ scor = SCORES_init(set_title,20);
33
+ scor->ref_fname = (char *)TEXT_strdup((TEXT *)ref_file);
34
+ scor->hyp_fname = (char *)TEXT_strdup((TEXT *)hyp_file);
35
+ scor->creation_date = get_date();
36
+ scor->frag_corr = fcorr;
37
+ scor->opt_del = opt_del;
38
+ if (wwl != (WWL*)0) {
39
+ scor->weight_ali = 1;
40
+ scor->weight_file =
41
+ (char *)TEXT_strdup((TEXT*)rsprintf("%s Column \"%s\"",wwl->filename,
42
+ wwl->weight_desc[0]));
43
+ } else if (lm_file != (char *)0) {
44
+ scor->weight_ali = 1;
45
+ scor->weight_file = (char *)TEXT_strdup((TEXT*)lm_file);
46
+ } else
47
+ scor->weight_ali = 0;
48
+
49
+ dbg=0;
50
+
51
+ if ((fp_hyp = fopen(hyp_file,"r")) == NULL){
52
+ fprintf(stderr,"Can't open input hypothesis file %s\n",hyp_file);
53
+ exit(1);
54
+ }
55
+ if ((fp_ref = fopen(ref_file,"r")) == NULL){
56
+ fprintf(stderr,"Can't open input reference file %s\n",ref_file);
57
+ exit(1);
58
+ }
59
+
60
+ hyp_eof = ref_eof = FALSE;
61
+ do {
62
+ if (dbg > 5) printf("Starting do-while loop on conversations"
63
+ "--------------------------\n");
64
+ fill_WTOKE_structure(hyp, fp_hyp, hyp_file, &hyp_eof, case_sense);
65
+ fill_WTOKE_structure(ref, fp_ref, ref_file, &ref_eof, case_sense);
66
+
67
+ if ((hyp->n < hyp->s) && (ref->n > ref->s)) {
68
+ fprintf(stderr,"Error: premature EOF in hyp file '%s' at conv"
69
+ "ersation '%s' of ref file '%s'\n",hyp_file,
70
+ ref->word[ref->s].conv,ref_file);
71
+ exit(1);
72
+ }
73
+ if ((hyp->n > hyp->s) && (ref->n < ref->s)) {
74
+ fprintf(stderr,"Error: premature EOF in ref file '%s' at conv"
75
+ "ersation '%s' of hyp file '%s'\n",ref_file,
76
+ hyp->word[hyp->s].conv,hyp_file);
77
+ exit(1);
78
+ }
79
+
80
+ locate_boundary(ref, ref->s, TRUE, FALSE, &ref_conv_end);
81
+ locate_boundary(hyp, hyp->s, TRUE, FALSE, &hyp_conv_end);
82
+
83
+ /* let's do some checking !!!!!! */
84
+ /* Are the conversations in sync */
85
+ if (strcmp(ref->word[ref->s].conv,hyp->word[hyp->s].conv)!=0){
86
+ fprintf(stderr,"Error: in ref file '%s' and hyp file '%s'\n",
87
+ ref_file, hyp_file);
88
+ fprintf(stderr," file strings out of "
89
+ "synchronization around ref-file='%s' hyp-file='%s'\n",
90
+ ref->word[ref->s].conv,hyp->word[hyp->s].conv);
91
+ exit(1);
92
+ }
93
+
94
+ locate_boundary(ref, ref->s, TRUE, TRUE, &ref_end_chan1);
95
+ locate_boundary(hyp, hyp->s, TRUE, TRUE, &hyp_end_chan1);
96
+
97
+ number_of_channels = 1;
98
+ hyp_end_chan2 = ref_end_chan2 = -1;
99
+ if (ref_end_chan1+1 < ref->n &&
100
+ strcmp(ref->word[ref->s].conv,ref->word[ref_end_chan1+1].conv)==0){
101
+ locate_boundary(ref, ref_end_chan1+1, TRUE, TRUE, &ref_end_chan2);
102
+ number_of_channels = 2;
103
+ }
104
+ if (hyp_end_chan1+1 < hyp->n &&
105
+ strcmp(hyp->word[hyp->s].conv,hyp->word[hyp_end_chan1+1].conv)==0){
106
+ locate_boundary(hyp, hyp_end_chan1+1, TRUE, TRUE, &hyp_end_chan2);
107
+ number_of_channels = 2;
108
+ }
109
+
110
+ if (number_of_channels == 2){
111
+ /* either the ref, hyp or both had two channels. make sure there */
112
+ /* are two channels in both */
113
+ if (hyp_end_chan2 == -1){
114
+ fprintf(stderr,"Error: in ref file '%s' and hyp file '%s'\n ",
115
+ ref_file, hyp_file);
116
+ fprintf(stderr," Hyp is missing second channel of file '%s'\n",
117
+ ref->word[ref->s].conv);
118
+ exit(1);
119
+ }
120
+ if (ref_end_chan2 == -1){
121
+ fprintf(stderr,"Error: in ref file '%s' and hyp file '%s'\n ",
122
+ ref_file, hyp_file);
123
+ fprintf(stderr," ref is missing second channel of file '%s'\n",
124
+ hyp->word[hyp->s].conv);
125
+ exit(1);
126
+ }
127
+
128
+
129
+ } else {
130
+ /* There was no second channel */
131
+ ref_end_chan2 = ref_end_chan1;
132
+ hyp_end_chan2 = hyp_end_chan1;
133
+ }
134
+
135
+ if (feedback >= 1)
136
+ printf(" Performing %s alignments for file '%s'.\n",
137
+ (time_align?"Time-mediated":"Word"),
138
+ ref->word[ref->s].conv);
139
+
140
+ if (dbg > 5){
141
+ printf("Located REF boundary: for %s %s -> %d,%d\n",
142
+ ref->word[ref->s].conv,
143
+ ref->word[ref->s].turn,ref->s,ref_conv_end);
144
+ printf("Located HYP boundary: for %s %s -> %d,%d\n",
145
+ hyp->word[hyp->s].conv,
146
+ hyp->word[hyp->s].turn,hyp->s,hyp_conv_end);
147
+
148
+ printf("Located REF Channel 1 boundary: for %d - %d\n",
149
+ ref->s,ref_end_chan1);
150
+ printf("Located HYP Channel 1 boundary: for %d - %d\n",
151
+ hyp->s,hyp_end_chan1);
152
+ printf("Located REF Channel 2 boundary: for %d - %d\n",
153
+ ref_end_chan1+1,ref_end_chan2);
154
+ printf("Located HYP Channel 2 boundary: for %d - %d\n",
155
+ hyp_end_chan1+1,hyp_end_chan2);
156
+ }
157
+
158
+
159
+ /* Start the alignment */
160
+ /* Side A */
161
+ for (i=0; i<number_of_channels; i++){
162
+ int base_len;
163
+ chunk = 0;
164
+ if (i==0){
165
+ ref_end = ref_end_chan1;
166
+ hyp_end = hyp_end_chan1;
167
+ ref_begin = ref->s;
168
+ hyp_begin = hyp->s;
169
+
170
+ ref_opp_end = ref_end_chan2;
171
+ hyp_opp_end = hyp_end_chan2;
172
+ ref_opp_begin = ref_end_chan1 + 1;
173
+ hyp_opp_begin = hyp_end_chan1 + 1;
174
+ } else {
175
+ ref_end = ref_end_chan2;
176
+ hyp_end = hyp_end_chan2;
177
+ ref_begin = ref_end_chan1 + 1;
178
+ hyp_begin = hyp_end_chan1 + 1;
179
+
180
+ ref_opp_end = ref_end_chan1;
181
+ hyp_opp_end = hyp_end_chan1;
182
+ ref_opp_begin = ref->s;
183
+ hyp_opp_begin = hyp->s;
184
+ }
185
+ if (dbg > 5){
186
+ printf("Starting channel %d\n",i);
187
+ printf("Ref Range: %d - %d\n",ref_begin,ref_end);
188
+ printf("Hyp Range: %d - %d\n",hyp_begin,hyp_end);
189
+ }
190
+ while (ref_begin<=ref_end || hyp_begin<=hyp_end){
191
+ int removals;
192
+
193
+ base_len = 50;
194
+ while (! chop_WTOKE_2(ref, hyp, ref_begin, hyp_begin,
195
+ ref_end, hyp_end, base_len,
196
+ &ref_chop_end,&hyp_chop_end)){
197
+ /* printf("Expanding len from %d to %d\n",base_len,
198
+ base_len*2); */
199
+ base_len *= 2;
200
+ }
201
+
202
+ removals = 0;
203
+
204
+ /* create the utterance ID */
205
+ sprintf(uttid,"(%s-%s-%04d)",ref->word[ref_begin].conv,
206
+ ref->word[ref_begin].turn,chunk);
207
+
208
+ spkr = SCORES_get_grp(scor,
209
+ rsprintf("%s-%s",
210
+ ref->word[ref_begin].conv,
211
+ ref->word[ref_begin].turn));
212
+
213
+ if (dbg > 5){
214
+ printf("Chunk %d: Starting for channel %d id=%s",
215
+ chunk,i,uttid);
216
+ printf(" Ref Range: %d - %d",ref_begin,ref_chop_end);
217
+ printf(" Hyp Range: %d - %d\n",hyp_begin,hyp_chop_end);
218
+ }
219
+
220
+
221
+ /* create the networks to be aligned */
222
+ if ((hnet=Network_create_from_WTOKE(hyp,hyp_begin,
223
+ hyp_chop_end,"Hypothesis net",
224
+ print_WORD_wt,
225
+ equal_WORD2,
226
+ release_WORD, null_alt_WORD,
227
+ opt_del_WORD,
228
+ copy_WORD,make_empty_WORD,
229
+ use_count_WORD,
230
+ left_to_right))
231
+ == NULL_NETWORK){
232
+ fprintf(stderr,"%s: Network_create_from_WTOKE failed\n",
233
+ proc);
234
+ return(0);
235
+ }
236
+ if ((rnet=Network_create_from_WTOKE(ref,ref_begin,
237
+ ref_chop_end,"Reference net",
238
+ print_WORD_wt,
239
+ equal_WORD2,
240
+ release_WORD, null_alt_WORD,
241
+ opt_del_WORD,
242
+ copy_WORD,make_empty_WORD,
243
+ use_count_WORD,
244
+ left_to_right))
245
+ == NULL_NETWORK){
246
+ fprintf(stderr,"%s: Network_create_from_WTOKE failed\n",
247
+ proc);
248
+ return(0);
249
+ }
250
+
251
+ path = network_dp_align_texts((TEXT *)0, rnet,
252
+ (TEXT *)0, hnet,
253
+ FALSE, case_sense,
254
+ (char *)uttid, fcorr,
255
+ opt_del, time_align, wwl, lm_file);
256
+ BF_SET(path->attrib,PA_HYP_WTIMES);
257
+ BF_SET(path->attrib,PA_REF_WTIMES);
258
+ if (ref->has_conf) BF_SET(path->attrib,PA_REF_CONF);
259
+ if (hyp->has_conf) BF_SET(path->attrib,PA_HYP_CONF);
260
+
261
+ sort_PATH_time_marks(path);
262
+
263
+ if (dbg > 10){
264
+ printf("After Sorting\n");
265
+ PATH_print_wt(path, stdout);
266
+ }
267
+
268
+ add_PATH_score(scor,path,spkr, keep_path);
269
+ PATH_add_file(path,ref->word[ref_begin].conv);
270
+ PATH_add_channel(path,ref->word[ref_begin].turn);
271
+ /* PATH_add_label(path,(char *)stm->seg[rs].labels); */
272
+
273
+ ref_begin = ref_chop_end+1;
274
+ hyp_begin = hyp_chop_end+1;
275
+
276
+ chunk++;
277
+ }
278
+ }
279
+
280
+
281
+ hyp->s = hyp_conv_end+1;
282
+ ref->s = ref_conv_end+1;
283
+
284
+ } while (hyp->s <= hyp->n || ref->s <= ref->n);
285
+
286
+ free_mark_file(ref);
287
+ free_mark_file(hyp);
288
+
289
+ fclose(fp_hyp);
290
+ fclose(fp_ref);
291
+
292
+ return (scor);
293
+ }
294
+
295
+ /*******************************************************************/
296
+ /* Compute the overlap of two segments in time and return that */
297
+ /* time. Negative times indicate no overlap. There are 6 cases */
298
+ /* Case 1: S1 t1 t2 */
299
+ /* S2 t1 t2 */
300
+ /* */
301
+ /* Case 2: S1 t1 t2 */
302
+ /* S2 t1 t2 */
303
+ /* */
304
+ /* Case 3a: S1 t1 t2 */
305
+ /* S2 t1 t2 */
306
+ /* */
307
+ /* Case 3b: S1 t1 t2 */
308
+ /* S2 t1 t2 */
309
+ /* */
310
+ /* Case 4a: S1 t1 t2 */
311
+ /* S2 t1 t2 */
312
+ /* */
313
+ /* Case 4b: S1 t1 t2 */
314
+ /* S2 t1 t2 */
315
+ /* */
316
+ double overlap(double s1_t1, double s1_t2, double s2_t1, double s2_t2)
317
+ {
318
+ double rval;
319
+ char *rule;
320
+ int dbg=0;
321
+ /* Case 1: */
322
+ if (s1_t2 < s2_t1)
323
+ rule="Case 1", rval=(s1_t2 - s2_t1);
324
+ /* Case 2: */
325
+ if (s1_t1 > s2_t2)
326
+ rule="Case 2", rval=(s2_t2 - s1_t1);
327
+ /* Case 3: */
328
+ if (s1_t1 < s2_t1){
329
+ /* Case 3a: */
330
+ if (s1_t2 < s2_t2)
331
+ rule="Case 3a", rval=(s1_t2 - s2_t1);
332
+ else /* Case 3b: */
333
+ rule="Case 3b", rval=(s2_t2 - s2_t1);
334
+ } else { /* Case 4: */
335
+ /* Case 4a: */
336
+ if (s1_t2 < s2_t2)
337
+ rule="Case 4a", rval=(s1_t2 - s1_t1);
338
+ else /* Case 4b: */
339
+ rule="Case 4b", rval=(s2_t2 - s1_t1);
340
+ }
341
+ if (dbg){
342
+ printf("Overlap: s1_t1=%2.2f s1_t2=%2.2f",s1_t1,s1_t2);
343
+ printf(" s2_t1=%2.2f s2_t2=%2.2f Rule:%s Rval=%2.2f\n",
344
+ s2_t1,s2_t2,rule,rval);
345
+ }
346
+ return(rval);
347
+ }
348
+
349
+
350
+ int chop_WTOKE_2(WTOKE_STR1 *ref, WTOKE_STR1 *hyp, int Rstart, int Hstart, int Rendconv, int Hendconv, int max_words, int *Rret_end, int *Hret_end)
351
+ {
352
+ int Rend, Hend, Rend_sync, Hend_sync;
353
+ char *proc="chop_WTOKE_2";
354
+ int dbg=0, skipped_alt;
355
+ double Rgap_t1, Rgap_t2, Hgap_t1, Hgap_t2;
356
+
357
+ if (dbg)
358
+ printf("%s: Start Ref=%d Start Hyp=%d Max_words=%d\n",
359
+ proc,Rstart,Hstart,max_words);
360
+
361
+ /* Find the end of this segment */
362
+ /* locate_boundary(ref, Rstart, TRUE, TRUE, &Rendconv);
363
+ locate_boundary(hyp, Hstart, TRUE, TRUE, &Hendconv); */
364
+
365
+ if (dbg) printf("%s: Conversation Rendconv=%d Hendconv=%d\n",
366
+ proc,Rendconv,Hendconv);
367
+
368
+ if ((Rstart > Rendconv) && (Hstart > Hendconv))
369
+ return(0);
370
+
371
+ /* if we've hit the end of the conversation, send everything */
372
+ if (((Rendconv - Rstart) <max_words) && ((Hendconv - Hstart) < max_words)){
373
+ *Rret_end = Rendconv;
374
+ *Hret_end = Hendconv;
375
+ if (dbg) printf("%s: R1 Success Chop Ref (%d-%d) Hyp (%d-%d)\n",
376
+ proc,Rstart,*Rret_end,Hstart,*Hret_end);
377
+ return(1);
378
+ }
379
+
380
+ /* set the indexes to maximum length */
381
+ Rend = MIN(Rstart + max_words, Rendconv);
382
+ Hend = MIN(Hstart + max_words, Hendconv);
383
+
384
+ if (dbg) printf("%s: Limited Rend=%d Hend=%d\n",proc,Rend,Hend);
385
+
386
+ /* synchronize the ends to permit searching */
387
+ while (Rend >= Rstart && ref->word[Rend].alternate)
388
+ Rend--;
389
+ skipped_alt = TRUE;
390
+ while (skipped_alt){
391
+ skipped_alt = FALSE;
392
+ if (ref->word[Rend].t1 > hyp->word[Hend].t1)
393
+ while (!skipped_alt &&
394
+ Rend >= Rstart &&
395
+ ref->word[Rend].t1 > hyp->word[Hend].t1 &&
396
+ overlap(ref->word[Rend].t1,
397
+ ref->word[Rend].t1+ref->word[Rend].dur,
398
+ hyp->word[Hend].t1,
399
+ hyp->word[Hend].t1+hyp->word[Hend].dur) < 0.0)
400
+ for (Rend--; Rend >= Rstart && ref->word[Rend].alternate; ) {
401
+ Rend--;
402
+ skipped_alt = TRUE;
403
+ }
404
+ else if (ref->word[Rend].t1 < hyp->word[Hend].t1)
405
+ while (Hend >= Hstart &&
406
+ ref->word[Rend].t1 < hyp->word[Hend].t1 &&
407
+ overlap(ref->word[Rend].t1,
408
+ ref->word[Rend].t1+ref->word[Rend].dur,
409
+ hyp->word[Hend].t1,
410
+ hyp->word[Hend].t1+hyp->word[Hend].dur) < 0.0)
411
+ Hend --;
412
+ }
413
+ if (dbg) {
414
+ printf("%s: Synchronized Rend=%d Hend=%d ",proc,Rend,Hend);
415
+ printf("Times: %2.2f,%2.2f %2.2f,%2.2f\n",
416
+ ref->word[Rend].t1, ref->word[Rend].t1+ref->word[Rend].dur,
417
+ hyp->word[Hend].t1, hyp->word[Hend].t1+hyp->word[Hend].dur);
418
+ }
419
+ Rend_sync = Rend;
420
+ Hend_sync = Hend;
421
+
422
+ /* begin the backward search */
423
+ while (Rend > Rstart && Hend > Hstart){
424
+ /* first compute t1 and t2 for the gap in each segment */
425
+ if (Rend >= Rstart){
426
+ Rgap_t1 = ref->word[Rend].t1 + ref->word[Rend].dur;
427
+ Rgap_t2 = (Rend == Rendconv) ? 999999.99 : ref->word[Rend+1].t1;
428
+ } else {
429
+ Rgap_t1 = 0.0;
430
+ Rgap_t2 = ref->word[Rstart].t1;
431
+ }
432
+ if (Hend >= Hstart) {
433
+ Hgap_t1 = hyp->word[Hend].t1 + hyp->word[Hend].dur;
434
+ Hgap_t2 = (Hend == Hendconv) ? 999999.99 : hyp->word[Hend+1].t1;
435
+ } else {
436
+ Hgap_t1 = 0.0;
437
+ Hgap_t2 = hyp->word[Hstart].t1;
438
+ }
439
+
440
+ if (dbg) {
441
+ printf("\n%s: Gaps: ref %2.2f,%2.2f hyp %2.2f,%2.2f\n",
442
+ proc,Rgap_t1, Rgap_t2, Hgap_t1, Hgap_t2);
443
+ printf("%s: **** middle word is Rend or Hend\n",proc);
444
+ dump_word_tokens2(ref,Rend-1,Rend+1);
445
+ dump_word_tokens2(hyp,Hend-1,Hend+1);
446
+ }
447
+
448
+ /* check to see if there is any overlap */
449
+ /* yes if : S1 | | # | | */
450
+ /* S2 | | # | | */
451
+
452
+ if (overlap(Rgap_t1,Rgap_t2,Hgap_t1,Hgap_t2) < 0.0){
453
+ /* no overlap decide which to move */
454
+
455
+ if (dbg) printf("%s: Shifting down\n",proc);
456
+
457
+ skipped_alt = TRUE;
458
+ while (skipped_alt){
459
+ skipped_alt = FALSE;
460
+ if (ref->word[Rend].t1 > hyp->word[Hend].t1){
461
+ if (Rend > Rstart) {
462
+ Rend --;
463
+ while (Rend >= Rstart && ref->word[Rend].alternate) {
464
+ Rend--;
465
+ skipped_alt = TRUE;
466
+ }
467
+ }
468
+ if (dbg) printf("%s: Moving Ref\n",proc);
469
+ while (!skipped_alt &&
470
+ Hend >= Hstart &&
471
+ ref->word[Rend].t1 < hyp->word[Hend].t1 &&
472
+ overlap(ref->word[Rend].t1,
473
+ ref->word[Rend].t1+ref->word[Rend].dur,
474
+ hyp->word[Hend].t1,
475
+ hyp->word[Hend].t1+hyp->word[Hend].dur)< 0.0){
476
+ Hend --;
477
+ if (dbg) printf("%s: Adjusting Hyp\n",proc);
478
+ }
479
+ } else if (ref->word[Rend].t1 <= hyp->word[Hend].t1) {
480
+ if (Hend > Hstart)
481
+ Hend --;
482
+ if (dbg) printf("%s: Moving Hyp\n",proc);
483
+ while (!skipped_alt &&
484
+ Rend >= Rstart &&
485
+ ref->word[Rend].t1 > hyp->word[Hend].t1 &&
486
+ overlap(ref->word[Rend].t1,
487
+ ref->word[Rend].t1+ref->word[Rend].dur,
488
+ hyp->word[Hend].t1,
489
+ hyp->word[Hend].t1+hyp->word[Hend].dur)<0.0){
490
+ for (Rend--;
491
+ Rend >= Rstart && ref->word[Rend].alternate; ) {
492
+ Rend--;
493
+ skipped_alt = TRUE;
494
+ }
495
+ if (dbg) printf("%s: Adjusting Ref\n",proc);
496
+ }
497
+ }
498
+ }
499
+ } else { /* Overlap exists !!!!! Return the values */
500
+ *Rret_end = Rend;
501
+ *Hret_end = Hend;
502
+ if (dbg) printf("%s: R2 Success Chop Ref (%d-%d) Hyp (%d-%d)\n",
503
+ proc,Rstart,*Rret_end,Hstart,*Hret_end);
504
+ return(1);
505
+ }
506
+ }
507
+
508
+ if (Rend > Rstart || Hend > Hstart){
509
+ *Rret_end = Rend;
510
+ *Hret_end = Hend;
511
+ if (dbg) printf("%s: R3 Success Chop Ref (%d-%d) Hyp (%d-%d)\n",
512
+ proc,Rstart,*Rret_end,Hstart,*Hret_end);
513
+ return(1);
514
+ }
515
+ /* fprintf(stdout,"%s: Failure to find chop'd segment, returning 0\n",proc); */
516
+ return(0);
517
+
518
+ }
SCTK/src/sclite/killarc1.o ADDED
Binary file (2.11 kB). View file
 
SCTK/src/sclite/llist.c ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** Mark Przybocki
2
+ ** Filename: LLIST.C
3
+ ** Module 1 used to build liblist.a (library).
4
+ **
5
+ **/
6
+
7
+ #include "sctk.h"
8
+
9
+ static LList *getLList(void *);
10
+ static void freeLList(LList **);
11
+ void recur(LList **t, LList *f);
12
+
13
+
14
+ /*
15
+ * Function GETLNODE returns a pointer to a lnode which will
16
+ * contain the data element taken as input.
17
+ */
18
+ static LList *getLList (void *pdata)
19
+ {
20
+ LList *ptemp; /* temporary lnode being set with data element */
21
+
22
+ /* ALLOCATE MEMORY for our TEMP LNODE */
23
+ ptemp = malloc(sizeof(LList));
24
+
25
+ if (ptemp != NULL) {
26
+ /* we have successfully allocated memory so set the LList */
27
+ ptemp -> data = pdata; /** DATA ELEMENT **/
28
+ ptemp -> next = NULL; /** NEXT LLIST NOT ASSIGNED YET **/
29
+ }
30
+
31
+ return ptemp; /** RETURNS either a Null LList or a set LList **/
32
+ }
33
+
34
+
35
+
36
+ /*
37
+ * Function FREELLIST deallocates space occupied by a LList and
38
+ * clears the LList from the list.
39
+ */
40
+ static void freeLList (LList **p)
41
+ {
42
+ free(*p); /** DEALLOCATE SPACE **/
43
+ *p=NULL; /** Clear value of *p **/
44
+ }
45
+
46
+
47
+
48
+ /*
49
+ * Function INIT_LIST sets the starting point of a list NULL,
50
+ * which infact gives existence to a list.
51
+ */
52
+ void LL_init (LList **s)
53
+ {
54
+ *s=NULL; /** creates a NULL list **/
55
+ }
56
+
57
+ void recur(LList **t, LList *f){
58
+ if (! LL_empty(f)){
59
+ recur(t,f->next);
60
+ LL_put_front(t,f->data);
61
+ }
62
+ }
63
+
64
+ void LL_copy (LList **t, LList **f)
65
+ {
66
+ LL_init(t);
67
+ recur(t,*f);
68
+ }
69
+
70
+
71
+
72
+ /*
73
+ * Function EMPTY test whether or not LLIST is empty.
74
+ */
75
+ int LL_empty (LList *s)
76
+ {
77
+ return ( s==NULL ); /** Test for existing list **/
78
+ }
79
+
80
+
81
+
82
+ /*
83
+ * Function PUSH places one LList at the head (top) of the list.
84
+ */
85
+ int LL_put_front (LList **s, void *pdata)
86
+ {
87
+ LList *ptemp; /** Temporary LList holder **/
88
+
89
+ /* Get space and set a LList */
90
+ ptemp = getLList(pdata);
91
+
92
+ /* Check for error */
93
+ if (ptemp == NULL)
94
+ return 0; /** FAILURE: Couldn't allocate space **/
95
+
96
+ /* Add to list */
97
+ ptemp -> next = *s;
98
+
99
+ /** Set the begining of the list **/
100
+ *s = ptemp;
101
+
102
+ return 1; /** SUCCESS **/
103
+ }
104
+
105
+ /*
106
+ * Function LL_put_tail places one LList at the tail (bottom) of the list.
107
+ */
108
+ int LL_put_tail (LList **s, void *pdata)
109
+ {
110
+ LList *ptemp, *pt1 = *s; /** Temporary LList holder **/
111
+
112
+ if (*s == (LList *)0)
113
+ return LL_put_front(s,pdata);
114
+
115
+ /* Get space and set a LList */
116
+ ptemp = getLList(pdata);
117
+
118
+ /* Check for error */
119
+ if (ptemp == NULL)
120
+ return 0; /** FAILURE: Couldn't allocate space **/
121
+
122
+ /* traverse to the end of the list */
123
+ while (pt1->next != NULL)
124
+ pt1 = pt1->next;
125
+
126
+ /* Add to list */
127
+ pt1 -> next = ptemp;
128
+ ptemp->next = (LList *)NULL;
129
+
130
+ return 1; /** SUCCESS **/
131
+ }
132
+
133
+
134
+
135
+ /*
136
+ * Function LL_get_first removes a LList for the head (top) of list.
137
+ */
138
+ int LL_get_first (LList **s, void **apdata)
139
+ {
140
+ LList *ptemp; /* Temporary LList holder */
141
+
142
+ if (LL_empty(*s) == 1)
143
+ return 0; /** list already empty nothing to pop **/
144
+
145
+ /* Set ptemp to the first LList */
146
+ ptemp = *s;
147
+
148
+ /* Reset to point to the following LList*/
149
+ *s = ptemp -> next;
150
+
151
+ /* Grab the data element */
152
+ *apdata = ptemp -> data;
153
+
154
+ /* Free the space of the popped LList */
155
+ freeLList (&ptemp);
156
+
157
+ return 1; /** Success **/
158
+ }
159
+
SCTK/src/sclite/llist.h ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ ** Mark Przybocki
3
+ ** 598 Unix/c
4
+ **
5
+ ** Project #7: PART I (creating a library)
6
+ **
7
+ ** Filename: LLIST.H
8
+ ** header file for the liblist.a library
9
+ ** and other linked list functions.
10
+ **
11
+ **/
12
+
13
+ /** DEFINE THE BASIC NODE STRUCTURE **/
14
+
15
+ typedef struct lnode LList;
16
+ struct lnode
17
+ {
18
+ void *data; /* data element */
19
+ void *next; /* pointer to next element */
20
+ };
21
+
22
+ /** FUNCTION PROTO-TYPING **/
23
+
24
+ /* file: llist.c */
25
+
26
+ int LL_put_tail(LList **, void *);
27
+ int LL_put_front(LList **, void *);
28
+ int LL_get_first(LList **, void **);
29
+ void LL_init(LList **);
30
+ void LL_copy(LList **, LList **);
31
+ int LL_empty(LList *);
32
+
SCTK/src/sclite/makefile.in ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # makefile for SCLITE
2
+
3
+ #### Start of system configuration section. ####
4
+
5
+ srcdir = @srcdir@
6
+ VPATH = @srcdir@
7
+
8
+ CC = @CC@
9
+ INSTALL = @INSTALL@
10
+
11
+ GNUDIFF = @DIFF@
12
+ CPPFLAGS = @CPPFLAGS@
13
+ DEFS = @DEFS@
14
+ CFLAGS = @CFLAGS@
15
+ LDFLAGS = @LDFLAGS@
16
+ SLM_TARGETS = @SLM_TARGETS@
17
+ LIBS = @LIBS@ $(SLM_TARGETS)
18
+
19
+ # Some System V machines do not come with libPW.
20
+ # If this is true for you, use the GNU alloca.o here.
21
+
22
+ prefix = @prefix@
23
+ exec_prefix = @exec_prefix@
24
+ edit_program_name = sed '@program_transform_name@'
25
+
26
+ bindir = $(exec_prefix)/bin
27
+ mandir =$(prefix)/man
28
+ man1dir =$(mandir)/man1
29
+ man5dir = $(mandir)/man5
30
+
31
+ infodir = $(prefix)/info
32
+
33
+ DEFAULT_EDITOR_PROGRAM = ed
34
+ NULL_DEVICE = /dev/null
35
+ PR_PROGRAM = /bin/pr
36
+
37
+ #### End of system configuration section. ####
38
+
39
+ SHELL = /bin/sh
40
+
41
+ ######################################################################
42
+ # The source files for all of the programs.
43
+ glib_c = order.c rsprintf.c path.c text.c scores.c word.c rpg.c statdist.c \
44
+ pad.c sgml.c readpipe.c alex.c sc_dtl.c det.c wwscr_f.c corresp.c \
45
+ slm_intf.c
46
+
47
+ statlib_c = rank.c range.c anovar.c signtest.c wilcoxon.c sentmcn.c mtchprs.c
48
+
49
+ netlib_c = addarc1.c delarc1.c llist.c marc1.c arcseq1.c \
50
+ mnode1.c boolpr1.c killarc1.c net_adt.c knode2.c net_dp.c
51
+
52
+ align_c = stm.c align.c dwtoke2.c fillmrks.c wtokeini.c lur.c stm2ctm.c \
53
+ ctm2ctm.c mfa.c cores.c
54
+
55
+
56
+ ######################################################################
57
+ # The Object files for all of the library code.
58
+ glib_o = order.o rsprintf.o path.o text.o scores.o word.o rpg.o statdist.o \
59
+ pad.o sgml.o readpipe.o alex.o sc_dtl.o det.o wwscr_f.o corresp.o \
60
+ slm_intf.o
61
+
62
+ statlib_o = rank.o range.o anovar.o signtest.o wilcoxon.o sentmcn.o mtchprs.o
63
+
64
+ netlib_o = addarc1.o delarc1.o llist.o marc1.o arcseq1.o \
65
+ mnode1.o boolpr1.o killarc1.o net_adt.o knode2.o net_dp.o
66
+
67
+ align_o = stm.o align.o dwtoke2.o fillmrks.o wtokeini.o lur.o stm2ctm.o \
68
+ ctm2ctm.o mfa.o cores.o
69
+
70
+ ######################################################################
71
+ # Group the libraries into their seperate forms either standalone or
72
+ # in the tool kit
73
+
74
+ sclib_c = $(glib_c) $(netlib_c) $(align_c)
75
+ tklib_c = $(sclib_c) $(statlib_c)
76
+
77
+ sclib_o = $(glib_o) $(netlib_o) $(align_o)
78
+ tklib_o = $(sclib_o) $(statlib_o)
79
+
80
+ SC_PROGRAMS = sclite
81
+ TK_PROGRAMS = $(SC_PROGRAMS) sc_stats rover sctkUnit
82
+
83
+ TEST_PROGRAMS = test test2 sc_conf mtchpath rover_v2 sc_quick mprint
84
+
85
+ PURIFY_PROGRAMS = $(PROGRAMS:%=%_pure) $(TEST_PROGRAMS:%=%_pure)
86
+
87
+ PURECOV_PROGRAMS = $(PROGRAMS:%=%_purecov)
88
+
89
+ DOCS = ../install.txt ../readme.txt ../disclaim.txt ../revision.txt \
90
+ ../makefile ../doc
91
+ CONFIG = makefile.in config.sh config.in config.txt
92
+
93
+ tk_distfiles = $(tklib_c) $(TK_PROGRAMS:%=%.c) *.h $(CONFIG) testdata
94
+
95
+ ######################################################################
96
+ ############### Defines the installation type #####################
97
+ lib_o = $(tklib_o)
98
+ lib_c = $(tklib_c)
99
+ PROGRAMS = $(TK_PROGRAMS)
100
+ distribution = tk_dist
101
+
102
+ #lib_o = $(sclib_o)
103
+ #lib_c = $(sclib_c)
104
+ #PROGRAMS = $(SC_PROGRAMS)
105
+ #distribution = sc_dist
106
+
107
+ ######################################################################
108
+
109
+
110
+ all: makefile $(SLM_TARGETS) $(PROGRAMS)
111
+
112
+
113
+ .c.o:
114
+ $(CC) -c $(OFLAGS) $(DEFS) -I. $(CFLAGS) $(CPPFLAGS) -o $@ $<
115
+
116
+ sclite: $(lib_o) sclite.o
117
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS)
118
+ sc_stats: $(lib_o) sc_stats.o
119
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS)
120
+ rover: $(lib_o) rover.o
121
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS)
122
+ mcnemar: $(lib_o) mcnemar.o
123
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS)
124
+ sctkUnit: $(lib_o) sctkUnit.o
125
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS)
126
+ sign: $(lib_o) sign.o
127
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS)
128
+ sclite_tolower: $(lib_o) sclite_tolower.o
129
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS)
130
+ $(TEST_PROGRAMS): $(lib_o) $$@.o
131
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS)
132
+ $(PURIFY_PROGRAMS): $(lib_o)
133
+ purify $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ `echo $@.c|sed 's/_pure//'` $(LIBS)
134
+ $(PURECOV_PROGRAMS): $(lib_o)
135
+ purecov $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ `echo $@.c|sed 's/_purecov//'` $(LIBS)
136
+
137
+ ### make a rule to compile the SLM toolkit
138
+ slm_v2/lib/SLM2.a:
139
+ (cd slm_v2/src && make SLM2.a install-lib)
140
+
141
+ #arpg: rpg.o arpg.o pad.o
142
+ # $(CC) -o $@ $(CFLAGS) $(LDFLAGS) rpg.o arpg.o pad.o $(LIBS)
143
+ clean:
144
+ rm -f *.o $(PROGRAMS) core
145
+ if test -f slm_v2/src/makefile ; then \
146
+ (cd slm_v2/src && make spotless) \
147
+ fi
148
+
149
+ mostlyclean: clean
150
+
151
+ distclean: clean
152
+ rm -rf *~ config.status config.log config.cache config.h makefile
153
+
154
+ realclean: distclean
155
+ rm -f TAGS *.info*
156
+
157
+ install: all testinstalldirs
158
+ set -e; for p in $(PROGRAMS); do \
159
+ $(INSTALL) $$p $(DESTDIR)$(bindir)/$$p; \
160
+ done
161
+ #REenable this later
162
+ # set -e; for p in `(cd ../doc ; ls *.1)`; do \
163
+ # $(INSTALL) ../doc/$$p $(DESTDIR)$(man1dir)/$$p; \
164
+ # done
165
+ # @echo "!!!! If 'man sclite' does not work, run 'catman -M $(mandir)'"
166
+ # @echo "!!!! to make manual pages accessible."
167
+
168
+ testinstalldirs:
169
+ @-set -e; for p in $(DESTDIR)$(bindir) $(DESTDIR)$(man1dir) $(DESTDIR)$(man5dir); do \
170
+ if test ! -d $$p ; then \
171
+ echo "Error: directory $$p doesn't exist"; \
172
+ fi ; \
173
+ done
174
+ #REenable this later
175
+ # if test ! -w $$p ; then \
176
+ # echo "Error: directory $$p is not writeable by you"; \
177
+ # fi \
178
+
179
+ # We need more tests.
180
+ check: sctkUnit
181
+ ./sctkUnit
182
+ cd testdata && ./tsclite.sh
183
+ cd testdata && ./tsc_stats.sh
184
+
185
+ uninstall:
186
+ set -e; for p in $(PROGRAMS); do \
187
+ rm -f $(bindir)/`echo $$p | $(edit_program_name)`; \
188
+ done
189
+ set -e; for p in `(cd ../doc ; ls *.1)`; do \
190
+ rm -f $(man1dir)/$$p; \
191
+ done
192
+
193
+ config.sh: config.in
194
+ cd $(srcdir) && /usr/local/bin/autoconf config.in | sed 's/Makefile/makefile/g' > config.sh
195
+
196
+ # autoheader might not change config.hin.
197
+ config.hin: stamp-h.in
198
+ stamp-h.in: config.in
199
+ cd $(srcdir) && autoheader
200
+ date > $(srcdir)/stamp-h.in
201
+
202
+ config.status: config.sh
203
+ ./config.status --recheck
204
+
205
+ # config.status might not change config.h, but it changes stamp-h.
206
+ makefile: makefile.in config.status
207
+ ./config.status
208
+
209
+ dist: $(distribution)
210
+
211
+ tk_dist: $(tk_distfiles)
212
+ echo sctk-`grep define\ TK_VERSION sctk.h | sed -e 's/^[^"]*"//' -e 's/"[^"]*//'` > .fname
213
+ echo "Distribution file '../`cat .fname`.tar.Z'"
214
+ (cd ../doc && ./export.sh $(PROGRAMS))
215
+ rm -rf ../`cat .fname`
216
+ mkdir ../`cat .fname`
217
+ (cd ./testdata && tsclite.sh -clean) ;
218
+ set -e; for file in $(DOCS); do \
219
+ ln -s $$file ../`cat .fname`; \
220
+ done
221
+ mkdir ../`cat .fname`/src
222
+ set -e; for file in $(tk_distfiles); do \
223
+ ln -s ../../src/$$file ../`cat .fname`/src/$$file; \
224
+ done
225
+ echo "Installing SLM links"
226
+ mkdir ../`cat .fname`/src/slm_v2
227
+ mkdir ../`cat .fname`/src/slm_v2/lib
228
+ mkdir ../`cat .fname`/src/slm_v2/bin
229
+ mkdir ../`cat .fname`/src/slm_v2/src
230
+ set -e; for file in readme.txt endian.sh include doc; do \
231
+ ln -s ../../../src/slm_v2/$$file ../`cat .fname`/src/slm_v2/$$file; \
232
+ done
233
+ echo " Copying SLM source"
234
+ tar cf - `find slm_v2/src \( -name makefile.in -o -name install-sh -o -name "*.[ch]" \) -print` | (cd ../`cat .fname`/src && tar xf -)
235
+ echo "Tar-ing SLM to make it ISO-compatable"
236
+ (cd ../`cat .fname`/src && tar chf slm_v2.tar ./slm_v2 && rm -r slm_v2)
237
+ (cd .. && tar -chf - --exclude=CVS `cat src/.fname` | compress > `cat src/.fname`.tar.Z)
238
+ rm -rf ../`cat .fname`
239
+ echo "Decompressing the release file"
240
+ (cd .. && zcat `cat src/.fname`.tar.Z | tar xf -)
241
+ echo "ISO_checking. . . . Only the top-level makefile should fail"
242
+ (cd .. && iso_check `cat src/.fname`)
243
+ rm -rf ../`cat .fname` .fname
244
+
245
+ # Prevent GNU make v3 from overflowing arg limit on SysV.
246
+ .NOEXPORT:
SCTK/src/sclite/marc1.c ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* file marc1.c */
2
+
3
+
4
+ #include "sctk.h"
5
+
6
+ ARC *make_arc(void *dat, NODE *from_node, NODE *to_node, int *perr)
7
+
8
+ /*********************************************************/
9
+ /* Makes an arc <from_node/symbol/to_node>, returning a */
10
+ /* pointer to it. */
11
+ /*********************************************************/
12
+ {char *proc = "make_arc";
13
+ ARC *p;
14
+ /* code */
15
+ db_enter_msg(proc,1); /* debug only */
16
+ p = (ARC *)malloc_safe(sizeof(ARC),proc);
17
+ *perr = 0;
18
+ p->data = dat;
19
+ p->weight = 0;
20
+ p->net = NULL_NETWORK;
21
+ p->from_node = from_node;
22
+ p->to_node = to_node;
23
+ db_leave_msg(proc,1); /* debug only */
24
+ return p;
25
+ } /* end make_arc() */
SCTK/src/sclite/mcnemar.c ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #define MAIN
2
+ #include "sctk.h"
3
+
4
+ int main(int argc, char **argv){
5
+ int **table;
6
+
7
+ alloc_2dimarr(table, 2, 2, int);
8
+ table[0][0] = 100;
9
+ table[0][1] = 200;
10
+ table[1][0] = 300;
11
+ table[1][1] = 400;
12
+
13
+ double conf;
14
+ do_McNemar(table, "Sys1", "Sys2", TRUE, stdout, &conf);
15
+
16
+
17
+
18
+ }
SCTK/src/sclite/mfa.c ADDED
@@ -0,0 +1,299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <sctk.h>
2
+
3
+ void locate_next_file_channel(WTOKE_STR1 **ctms, int nctms, FILE **files, char **hypname, int *eofs, int *conv_end, int case_sense, int feedback);
4
+ void print_linear(NODE *node, void *p);
5
+ int gap_at_times(WTOKE_STR1 *ctm, int end, double *mgap_beg, double *mgap_end, int *mgap_s);
6
+ NETWORK *perform_mfalign(WTOKE_STR1 **ctms, int nctm, int *sil_end, int time_align);
7
+ void populate_tag1(NODE *node, void *p);
8
+
9
+ int mfdb = 0;
10
+ int glob_ties = 0;
11
+
12
+ void mfalign_ctm_files(char **hypname, int nhyps, int time_align, int case_sense, int feedback, void (*callback)(NETWORK *, char *, char *), double silence_dur){
13
+ char *proc = "mfalign_ctm_files";
14
+ WTOKE_STR1 **ctms;
15
+ NETWORK *mfnet;
16
+ FILE **files;
17
+ int *eofs, *conv_end, *sil_end;
18
+ int in;
19
+ int done;
20
+ NETWORK *cor;
21
+ char *file, *chan;
22
+
23
+
24
+ {if (getenv("MFALIGN_DBG") != NULL) {
25
+ mfdb=(int)atof(getenv("MFALIGN_DBG")); }}
26
+
27
+ if (feedback > 1) printf("Beginning: %s\n",proc);
28
+ /* ALLOCATE MEMORY */
29
+ alloc_singZ(ctms,nhyps,WTOKE_STR1 *,(WTOKE_STR1 *)0);
30
+ alloc_singZ(files,nhyps,FILE *,(FILE *)0);
31
+ alloc_singZ(eofs,nhyps,int,0);
32
+ alloc_singZ(conv_end,nhyps,int,0);
33
+ alloc_singZ(sil_end,nhyps,int,0);
34
+
35
+ /* OPEN FILES, INIT WTOKE'S, FILE WTOKE'S */
36
+ for (in=0; in < nhyps; in++){
37
+ if ((files[in] = fopen(hypname[in],"r")) == NULL){
38
+ fprintf(stderr,"Can't open input hypothesis file %s\n",hypname[in]);
39
+ exit(1);
40
+ }
41
+ ctms[in] = WTOKE_STR1_init(hypname[in]);
42
+ }
43
+ done = 0;
44
+ while (!done){
45
+ locate_next_file_channel(ctms, nhyps, files, hypname, eofs, conv_end,
46
+ case_sense, feedback);
47
+
48
+ file = ctms[0]->word[ctms[0]->s].conv;
49
+ chan = ctms[0]->word[ctms[0]->s].turn;
50
+
51
+ /* loop though the file/channel section, looking for time breaks */
52
+ while(find_common_silence(ctms, nhyps, conv_end,
53
+ sil_end, silence_dur) == 1){
54
+ if (mfdb >= 5){
55
+ printf("--------- Aligning this chunk -----------\n");
56
+
57
+ for (in=0; in<nhyps; in++){
58
+ double beg, end;
59
+ beg = (ctms[in]->s > conv_end[in]) ? -1.0 :
60
+ ctms[in]->word[sil_end[in]].t1 +
61
+ ctms[in]->word[sil_end[in]].dur;
62
+ end = (sil_end[in] < conv_end[in]) ?
63
+ ctms[in]->word[sil_end[in]+1].t1 : 9999999.9;
64
+ printf(" CTM %d: start: %d end_word: %d start: %.2f"
65
+ " end: %.2f\n",in,ctms[in]->s,sil_end[in],beg,end);
66
+ }
67
+ }
68
+
69
+ mfnet = perform_mfalign(ctms,nhyps,sil_end,time_align);
70
+ Network_traverse(mfnet,populate_tag1,(void *)hypname,0,0,0);
71
+ cor = Network_WORD_to_CORES(mfnet);
72
+
73
+ callback(cor, file, chan);
74
+
75
+ Network_destroy(cor);
76
+ Network_destroy(mfnet);
77
+
78
+ /* skip over this chunk because we're done with it. */
79
+ done = 1;
80
+ for (in=0; in < nhyps; in++){
81
+ ctms[in]->s = sil_end[in] +
82
+ ((sil_end[in] <= conv_end[in]) ? 1 : 0);
83
+ if (!eofs[in] || (ctms[in]->s < ctms[in]->n)) done = 0;
84
+ }
85
+ }
86
+ }
87
+ if (glob_ties > 0)
88
+ fprintf(stderr,"Warning: %d ties were arbitrarily broken\n",glob_ties);
89
+
90
+ /* FREE THE MEMORY */
91
+ free_singarr(eofs, int);
92
+ free_singarr(conv_end, int);
93
+ free_singarr(sil_end, int);
94
+ for (in=0; in<nhyps; in++) {
95
+ free_mark_file(ctms[in]);
96
+ fclose(files[in]);
97
+ }
98
+ free_singarr(files, FILE *);
99
+ free_singarr(ctms,WTOKE_STR1 *);
100
+ cleanup_NET_ALIGN();
101
+ }
102
+
103
+ NETWORK *perform_mfalign(WTOKE_STR1 **ctms, int nctm, int *end, int time_align){
104
+ char *proc = "perform_mfalign";
105
+ NETWORK **nets, *out_net;
106
+ WORD *null_alt;
107
+ int in;
108
+
109
+ alloc_singZ(nets,nctm,NETWORK *,(NETWORK *)0);
110
+ null_alt = new_WORD((TEXT *)"@",-1,0.0,0.0,0.0,(TEXT *)0,(TEXT *)0,0,0,-1.0);
111
+
112
+ /* create the networks */
113
+ for (in=0; in < nctm; in++){
114
+ if ((nets[in]=
115
+ Network_create_from_WTOKE(ctms[in],ctms[in]->s,end[in],
116
+ rsprintf("mfalign net %d",in),
117
+ print_WORD_wt,
118
+ equal_WORD2,
119
+ release_WORD, null_alt_WORD,
120
+ opt_del_WORD,
121
+ copy_WORD, make_empty_WORD,
122
+ use_count_WORD,
123
+ 1))
124
+ == NULL_NETWORK){
125
+ fprintf(stderr,"%s: Network_create_from_WTOKE failed\n",proc);
126
+ exit(1);
127
+ }
128
+ /* Network_traverse(nets[in],0,0,set_tag1,(void *)ctms[in]->id,0); */
129
+ }
130
+
131
+ /* align the networks */
132
+ Network_dpalign_n_networks(nets,nctm,(!time_align)?wwd_WORD_rover:wwd_time_WORD,
133
+ &out_net,(void *)null_alt);
134
+
135
+ /* delete the networks */
136
+ for (in=0; in < nctm; in++)
137
+ Network_destroy(nets[in]);
138
+
139
+ free_singarr(nets,NETWORK *);
140
+ release_WORD(null_alt);
141
+
142
+ return(out_net);
143
+ }
144
+
145
+
146
+ void locate_next_file_channel(WTOKE_STR1 **ctms, int nctm, FILE **files, char **hypname, int *eofs, int *conv_end, int case_sense, int feedback){
147
+ int in;
148
+
149
+ /* locate the file boundaries */
150
+ for (in=0; in < nctm; in++){
151
+ fill_WTOKE_structure(ctms[in], files[in], hypname[in],
152
+ &(eofs[in]), case_sense);
153
+ locate_boundary(ctms[in], ctms[in]->s, TRUE,TRUE,&(conv_end[in]));
154
+ if (in >= 1 && ctms[in]->s <= ctms[in]->n)
155
+ if (strcmp(ctms[0]->word[ctms[0]->s].conv,
156
+ ctms[in]->word[ctms[in]->s].conv) != 0){
157
+ fprintf(scfp,"Error: Conversation mismatches in %s and %s, "
158
+ "%s and %s respectively",hypname[0],hypname[in],
159
+ ctms[0]->word[ctms[0]->s].conv,
160
+ ctms[in]->word[ctms[in]->s].conv);
161
+ exit(1);
162
+ }
163
+ }
164
+ if (feedback >= 1) {
165
+ printf("Working on conversation: %s channel: %s\n",
166
+ ctms[0]->word[ctms[0]->s].conv,
167
+ ctms[0]->word[ctms[0]->s].turn);
168
+ for (in=0; in < nctm; in++)
169
+ printf(" File: %s range %d-%d\n",hypname[in],ctms[in]->s,
170
+ conv_end[in]);
171
+ }
172
+ }
173
+
174
+ /* This function looks for common periods of silence to all the WTOKE
175
+ * structures
176
+ */
177
+ int find_common_silence(WTOKE_STR1 **ctms, int nctm, int *ctm_end, int *sil_end, double silence_dur){
178
+ double mgap_beg, mgap_end;
179
+ int nc, failed, more_data;
180
+ int dbg = 0;
181
+
182
+ {if (getenv("MFALIGN_COMMON_SIL_DBG") != NULL) {
183
+ dbg=(int)atof(getenv("MFALIGN_COMMON_SIL_DBG")); }}
184
+
185
+ /* locate a gap in the master, ctms[0] */
186
+ sil_end[0] = ctms[0]->s;
187
+ while (sil_end[0] <= ctm_end[0]){
188
+ /* set the gap betwen this word and the next */
189
+ mgap_beg = ctms[0]->word[sil_end[0]].t1 +ctms[0]->word[sil_end[0]].dur;
190
+ /* if there is no next word, make it the end of time */
191
+ mgap_end = (sil_end[0] < ctm_end[0]) ? ctms[0]->word[sil_end[0]+ 1].t1:
192
+ 9999999.9 ;
193
+
194
+ if (mgap_end > mgap_beg + silence_dur){
195
+ if (dbg) printf("Found a gap %d (%.2f-%.2f) = %.2f\n",
196
+ sil_end[0],mgap_beg,mgap_end,mgap_end-mgap_beg);
197
+ for (nc=1, failed=0; nc<nctm && !failed; nc++){
198
+ if (gap_at_times(ctms[nc],ctm_end[nc],
199
+ &mgap_beg,&mgap_end,&sil_end[nc]) == 1){
200
+ if (dbg) printf(" Gap in %d\n",nc);
201
+ } else {
202
+ failed = 1;
203
+ }
204
+ }
205
+ if (failed != 1){
206
+ if (dbg) printf("Segment defined at:\n");
207
+ return(1);
208
+ }
209
+ }
210
+ sil_end[0] ++;
211
+ }
212
+ /* ctm[0] is at the end of the road, move all the other ctms to the
213
+ * end as well. If there is data left in them, return 1
214
+ */
215
+ if (dbg) printf("*** ctm[0] has ran out of data\n");
216
+ more_data = 0;
217
+ for (nc=0; nc<nctm; nc++){
218
+ sil_end[nc] = ctm_end[nc];
219
+ if (ctms[nc]->s <= ctm_end[nc]) more_data=1;
220
+ }
221
+ return (more_data);
222
+ }
223
+
224
+ void populate_tag1(NODE *node, void *p){
225
+ char **tags = (char **)p;
226
+ int Narc, f, *use, arc;
227
+ ARC_LIST_ATOM *parc;
228
+
229
+ if (node != NULL && strcmp(node->name,"STOP") != 0){
230
+ /* count the arcs */
231
+ for (Narc=0, parc=node->out_arcs; parc != (ARC_LIST_ATOM *)0;
232
+ parc = parc->next)
233
+ Narc++;
234
+ alloc_singZ(use,Narc,int,-1);
235
+ /* map the usage */
236
+ for (arc = 0, parc=node->out_arcs; parc != (ARC_LIST_ATOM *)0;
237
+ parc = parc->next, arc++){
238
+ /* Eprintf(" %s\n",((WORD*)(parc->arc->data))->value); */
239
+ if (TEXT_strcmp(((WORD*)(parc->arc->data))->value,(TEXT *)"@") != 0){
240
+ /* reset that systems use pointer */
241
+ for (f=0; f<Narc; f++){
242
+ if (TEXT_strcmp(((WORD*)(parc->arc->data))->tag1,(TEXT*)tags[f]) == 0)
243
+ use[arc] = f;
244
+ }
245
+ }
246
+ }
247
+ /* dump_singarr(use,Narc," %d",stdout); */
248
+ for (arc = 0, parc=node->out_arcs; parc != (ARC_LIST_ATOM *)0;
249
+ parc = parc->next, arc++)
250
+ if (use[arc] < 0){
251
+ int hit = -1, y;
252
+ /* printf(" Arc %d not tagged\n",arc); */
253
+ for (f=0; f<Narc && hit < 0; f++){
254
+ hit = f;
255
+ /* printf(" is %d used? \n",f); */
256
+ /* does any of the use elements == f */
257
+ for (y=0; y<Narc; y++)
258
+ if (use[y] == f)
259
+ hit = -1;
260
+ /* printf(" %d\n",hit); */
261
+ }
262
+ if (hit >= 0){
263
+ ((WORD*)(parc->arc->data))->tag1 = TEXT_strdup((TEXT*)tags[hit]);
264
+ use[arc] = hit;
265
+ }
266
+ }
267
+ /* printf(" "); dump_singarr(use,Narc," %d",stdout); */
268
+
269
+ free_singarr(use,int);
270
+ }
271
+
272
+ }
273
+
274
+ int gap_at_times(WTOKE_STR1 *ctm, int end, double *mgap_beg, double *mgap_end, int *mgap_s){
275
+ int i;
276
+ double gap_end, gap_beg;
277
+
278
+ /* if there is no more data in this ctm, that answer is YES */
279
+ if (ctm->s > end) {
280
+ *mgap_s = ctm->s;
281
+ return(1);
282
+ }
283
+
284
+ for (i=ctm->s; i<=end; i++){
285
+ gap_beg = ctm->word[i].t1 + ctm->word[i].dur;
286
+ gap_end = (i < end) ? ctm->word[i+1].t1 : 9999999.9;
287
+ if (overlap(*mgap_beg,*mgap_end,gap_beg,gap_end) > 0.0){
288
+ *mgap_s = i;
289
+ /* printf(" Gap@ %d times %.2f to %.2f\n",
290
+ i,gap_beg,gap_end); */
291
+ *mgap_beg = MAX(*mgap_beg,gap_beg);
292
+ *mgap_end = MIN(*mgap_end,gap_end);
293
+ /* printf(" Reset gap times to %.2f-%.2f\n",
294
+ *mgap_beg,*mgap_end); */
295
+ return (1);
296
+ }
297
+ }
298
+ return(0);
299
+ }
SCTK/src/sclite/mnode1.c ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* file mnode1.c */
2
+
3
+ #include "sctk.h"
4
+
5
+ NODE *make_node(char *name, NETWORK *net, ARC *from_arc, ARC *to_arc, int *highest_nnode_name, int *perr)
6
+
7
+ /************************************************************/
8
+ /* Makes a new node, returns a pointer to it. */
9
+ /* The new node is initialized with name, from_arc, to_arc. */
10
+ /* Set to be neither start not stop state. */
11
+ /* All boolean flags are initialized to F. */
12
+ /* If name is NULL, uses a char string version of bumped */
13
+ /* *highest_nnode_name for the new node name. */
14
+ /************************************************************/
15
+ {char *proc = "make_node";
16
+ char sxx[LINE_LENGTH], *sx = &sxx[0];
17
+ NODE *p;
18
+ /* code */
19
+ db_enter_msg(proc,1); /* debug only */
20
+ p = (NODE *)malloc_safe(sizeof(NODE),proc);
21
+ *perr = 0;
22
+ if (name != NULL)
23
+ {p->name = strdup_safe(name,proc);
24
+ }
25
+ else
26
+ {/* make name from node number */
27
+ *highest_nnode_name += 1;
28
+ sprintf(sx,"%d",*highest_nnode_name);
29
+ p->name = strdup_safe(sx,proc);
30
+ }
31
+ p->net = net ;
32
+ p->in_arcs = NULL;
33
+ p->out_arcs = NULL;
34
+ p->start_state = F;
35
+ p->stop_state = F;
36
+ p->flag1 = F;
37
+ p->flag2 = F;
38
+ if (from_arc != NULL){
39
+ p->in_arcs = add_to_arc_list(p->in_arcs,from_arc,perr);
40
+ if (*perr > 0) {
41
+ printf("%s:*ERR: add_to_arc_list() returns %d\n",proc,*perr);
42
+ return((NODE *)0);
43
+ }
44
+ }
45
+ if (to_arc != NULL) {
46
+ p->out_arcs = add_to_arc_list(p->out_arcs,to_arc,perr);
47
+ if (*perr > 0) {
48
+ printf("%s:*ERR: add_to_arc_list() returns %d\n",proc,*perr);
49
+ return((NODE *)0);
50
+ }
51
+ }
52
+ db_leave_msg(proc,1); /* debug only */
53
+ return p;
54
+ } /* end make_node() */
55
+
SCTK/src/sclite/mtchprs.c ADDED
@@ -0,0 +1,833 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**********************************************************************/
2
+ /* */
3
+ /* FILENAME: matched_pairs.c */
4
+ /* BY: Jonathan G. Fiscus */
5
+ /* DATE: April 14 1989 */
6
+ /* NATIONAL INSTITUTE OF STANDARDS AND TECHNOLOGY */
7
+ /* SPEECH RECOGNITION GROUP */
8
+ /* */
9
+ /* DESCRIPTION: These programs perform the Matched Pairs */
10
+ /* tests. which include: */
11
+ /* SEGMENTATION ANALYSIS */
12
+ /* MATCHED PAIRS TEST FOR SYSTEMS */
13
+ /* */
14
+ /**********************************************************************/
15
+
16
+
17
+ #include "sctk.h"
18
+
19
+ /**********************************************************************/
20
+ /* structures and defines for the sentence segment list */
21
+ #define MIN_NUM_GOOD 2
22
+ #define MAX_SEG_ANAL 10
23
+
24
+ #ifdef __cplusplus
25
+ extern "C" {
26
+ #endif
27
+
28
+ typedef struct segment_count_struct{
29
+ int number_ref;
30
+ int number_errors_for_hyp1;
31
+ int number_errors_for_hyp2;
32
+ } SEG;
33
+
34
+ #ifdef __cplusplus
35
+ }
36
+ #endif
37
+
38
+ /* alloc a segment list */
39
+ #define alloc_SEG_LIST(_seg,_num) \
40
+ alloc_2dimarr(_seg,_num,1,SEG);
41
+
42
+ #define expand_SEG_LIST(_seg_l,_num,_max) \
43
+ { int _l;\
44
+ expand_1dim(_seg_l,_num,_max,2.0,SEG *,1); \
45
+ for (_l=_num; _l < _max; _l++) \
46
+ alloc_singarr((_seg_l)[_l],1,SEG); \
47
+ }
48
+
49
+ #define free_SEG_LIST(_seg,_num) free_2dimarr(_seg,_num,SEG)
50
+
51
+
52
+ /* macros to access the segment list */
53
+ #define seg_n(_sg,_s) _sg[_s]
54
+ #define seg_ref(_sg,_s) _sg[_s]->number_ref
55
+ #define seg_hyp1(_sg,_s) _sg[_s]->number_errors_for_hyp1
56
+ #define seg_hyp2(_sg,_s) _sg[_s]->number_errors_for_hyp2
57
+
58
+
59
+ void evaluate_SEG(char *sys1_str, char *sys2_str, SEG **seg_l, int *num_seg, int sent_cnt, int min_good, double *s1_pct, double *s2_pct, double *seg_per_sent, int verbose, FILE *fp);
60
+ int analyze_Z_score(SCORES *sys1, SCORES *sys2, double mean, double variance, double std_dev, double Z_stat, int verbose);
61
+ void test_comp_sents(PATH *snt1, PATH *snt2, SEG ***seg_l, int *num_seg, int *max_seg, int min_good);
62
+ void count_seg(PATH *snt1, PATH *snt2, int beg1, int beg2, int end1, int end2, SEG ***seg_l, int *num_seg, int *max_seg, int dbg);
63
+ void seg_count(PATH *snt, int from, int to, int *err, int *ref);
64
+ void print_sent_seg_averaged_analysis(SCORES *scor[], int nscor, double ***seg_per_sent, char *tname);
65
+ void print_sent_seg_long_analysis(SCORES *scor[], int nscor, double ***seg_per_sent, char *tname);
66
+ void print_compare_matrix_for_sys(SCORES *scor[], int nscor, int **winner, char *matrix_name, char *tname, char *v_desc, double **sys1_pct_arr, double **sys2_pct_arr, int **num_seg, double **Z_stat, int min_num_good, FILE *fp);
67
+
68
+ /**********************************************************************/
69
+ /* this procedure is written to analyze the segmentation for */
70
+ /* varying numbers on the minimum number of good words to bound */
71
+ /* the beginning and the ends of the segments */
72
+ /**********************************************************************/
73
+ void do_mtch_pairs_seg_analysis(SCORES *scor[], int nscor, char *t_name, int seg_ave, int seg_long)
74
+ {
75
+ int sys1, sys2, min_g;
76
+ int result;
77
+ double conf;
78
+ int **num_seg, **max_seg;
79
+ double **sys1_pct_arr, **sys2_pct_arr, **Z_stat_arr, ***seg_per_sent;
80
+
81
+ /* do all allocations */
82
+ fprintf(stderr,"Doing segmentation analysis. This is slow so . . . \n\n");
83
+ alloc_2dimarr(num_seg,nscor,nscor,int);
84
+ alloc_2dimZ(max_seg,nscor,nscor,int,100);
85
+ alloc_2dimarr(sys1_pct_arr,nscor,nscor,double);
86
+ alloc_2dimarr(sys2_pct_arr,nscor,nscor,double);
87
+ alloc_2dimarr(Z_stat_arr,nscor,nscor,double);
88
+ alloc_3dimZ(seg_per_sent,MAX_SEG_ANAL,nscor,nscor,double,0.0);
89
+
90
+ /* loop for min_good, and compared systems */
91
+ for (min_g=0; min_g < MAX_SEG_ANAL; min_g++){
92
+ fprintf(stderr," calculating buffer of %d\n",min_g);
93
+ for (sys1=0; sys1 <(nscor-1); sys1++)
94
+ for (sys2=sys1+1; sys2<(nscor); sys2++){
95
+ result = do_mtch_pairs_on_sys(scor, nscor,sys1,sys2,
96
+ &(sys1_pct_arr[sys1][sys2]),
97
+ &(sys2_pct_arr[sys1][sys2]),
98
+ &(num_seg[sys1][sys2]),
99
+ &(max_seg[sys1][sys2]),
100
+ &(Z_stat_arr[sys1][sys2]),
101
+ &(seg_per_sent[min_g][sys1][sys2]),
102
+ min_g+1,FALSE,stdout,&conf);
103
+ }
104
+ }
105
+
106
+ /* if the flag, print the requested analysis */
107
+ if (seg_long)
108
+ print_sent_seg_long_analysis(scor,nscor,seg_per_sent,t_name);
109
+ if (seg_ave)
110
+ print_sent_seg_averaged_analysis(scor,nscor,seg_per_sent,t_name);
111
+
112
+ free_2dimarr(num_seg,nscor,int);
113
+ free_2dimarr(max_seg,nscor,int);
114
+ free_2dimarr(sys1_pct_arr,nscor,double);
115
+ free_2dimarr(sys2_pct_arr,nscor,double);
116
+ free_2dimarr(Z_stat_arr,nscor,double);
117
+ free_3dimarr(seg_per_sent,MAX_SEG_ANAL,nscor,double);
118
+ }
119
+
120
+
121
+ /**********************************************************************/
122
+ /* this procedure performs a single matched paired analysis for the */
123
+ /* one level of the min_good and returns the results in the winner */
124
+ /* array */
125
+ /**********************************************************************/
126
+ void do_mtch_pairs(SCORES *scor[], int nscor, char *min_num_good_str, char *test_name, int print_report, int verbose, int ***out_winner, char *outroot, int feedback, double ***out_conf)
127
+ {
128
+ int sys1, sys2;
129
+ int result, **winner;
130
+ double **conf;
131
+ int *sum_winner, **num_seg, min_num_good, **max_seg;
132
+ double **sys1_pct_arr, **sys2_pct_arr, **Z_stat_arr, **seg_per_sent;
133
+ char *matrix_name = "COMPARISON MATRIX: FOR THE MATCHED PAIRS TEST";
134
+ char *mean_desc = "PECENTAGES ARE MEAN PCT ERROR/SEGMENT. FIRST # IS LEFT SYSTEM";
135
+ FILE *fp = stdout;
136
+
137
+ if (print_report || verbose){
138
+ char *f = rsprintf("%s.mapsswe",outroot);
139
+ if ((fp=(strcmp(outroot,"-") == 0) ? stdout : fopen(f,"w")) ==
140
+ (FILE *)0){
141
+ fprintf(stderr,"Warning: Open of %s for write failed. "
142
+ "Using stdout instead.\n",f);
143
+ fp = stdout;
144
+ } else
145
+ if (feedback >= 1) printf(" Output written to '%s'\n",f);
146
+ }
147
+ if ((min_num_good = atoi(min_num_good_str)) <= 0){
148
+ fprintf(stderr,"Warning: Minimum seperation by correct words is \n");
149
+ fprintf(stderr," too low, setting to %d\n",
150
+ DEFAULT_MIN_NUM_GOOD);
151
+ min_num_good = DEFAULT_MIN_NUM_GOOD;
152
+ }
153
+ if (!print_report) verbose = FALSE;
154
+
155
+ /* all allocations */
156
+ alloc_2dimarr(num_seg,nscor,nscor,int);
157
+ alloc_2dimZ(max_seg,nscor,nscor,int,100);
158
+ alloc_2dimarr(sys1_pct_arr,nscor,nscor,double);
159
+ alloc_2dimarr(sys2_pct_arr,nscor,nscor,double);
160
+ alloc_2dimarr(Z_stat_arr,nscor,nscor,double);
161
+ alloc_2dimZ(seg_per_sent,nscor,nscor,double,0.0);
162
+ alloc_singZ(sum_winner,nscor,int,NO_DIFF);
163
+ alloc_2dimZ(winner,nscor,nscor,int,NO_DIFF);
164
+ *out_winner = winner;
165
+ alloc_2dimZ(conf,nscor,nscor,double,0.0);
166
+ *out_conf = conf;
167
+
168
+ /* loop each pair of compared systems */
169
+ for (sys1=0; sys1 <(nscor-1); sys1++)
170
+ for (sys2=sys1+1; sys2<(nscor); sys2++){
171
+ result = do_mtch_pairs_on_sys(scor,nscor,sys1,sys2,
172
+ &(sys1_pct_arr[sys1][sys2]),
173
+ &(sys2_pct_arr[sys1][sys2]),
174
+ &(num_seg[sys1][sys2]),
175
+ &(max_seg[sys1][sys2]),
176
+ &(Z_stat_arr[sys1][sys2]),
177
+ &(seg_per_sent[sys1][sys2]),
178
+ min_num_good,verbose,fp,
179
+ &(conf[sys1][sys2]));
180
+ winner[sys1][sys2] = result;
181
+ sum_winner[sys2] += result * (-1);
182
+ sum_winner[sys1] += result;
183
+ }
184
+
185
+ /* if print_report print the requested analysis */
186
+ if (print_report){
187
+ if (verbose) form_feed(fp);
188
+ print_compare_matrix_for_sys(scor,nscor,winner,matrix_name,test_name,
189
+ mean_desc,sys1_pct_arr,sys2_pct_arr,
190
+ num_seg,Z_stat_arr,min_num_good,fp);
191
+ if (fp == stdout) form_feed(fp);
192
+ }
193
+
194
+ free_2dimarr(sys1_pct_arr,nscor,double);
195
+ free_2dimarr(sys2_pct_arr,nscor,double);
196
+ free_2dimarr(Z_stat_arr,nscor,double);
197
+ free_2dimarr(seg_per_sent,nscor,double);
198
+ free_singarr(sum_winner,int);
199
+ free_2dimarr(num_seg,nscor,int);
200
+ free_2dimarr(max_seg,nscor,int);
201
+ /* Big Error free_2dimarr(conf,nscor,double); */
202
+
203
+ if (fp != stdout) fclose(fp);
204
+ }
205
+
206
+ /**********************************************************************/
207
+ /* the guts of the Matched Pairs program, this procedure compares */
208
+ /* 2 systems in a SYS_ALIGN_LIST with indexes sys1_ind and sys2_ind */
209
+ /* then goes through each matching sentence then calls another */
210
+ /* procedure to find the segments and store them in the segment */
211
+ /* list. after all sentences are compared, the segment list is */
212
+ /* analyzed */
213
+ /**********************************************************************/
214
+ int do_mtch_pairs_on_sys(SCORES *scor[], int nscor, int sys1_ind, int sys2_ind, double *sys1_pct, double *sys2_pct, int *num_seg, int *max_seg, double *Z_stat, double *seg_per_sent, int min_num_good, int verbose,FILE *fp, double *conf)
215
+ {
216
+ int spk1, spk2, snt1, snt2, i, sent_cnt=0, *err_diff;
217
+ double mean, std_dev, variance, median;
218
+ SCORES *sys1, *sys2;
219
+ SEG **seg_l;
220
+
221
+ *num_seg = 0;
222
+ sys1 = scor[sys1_ind];
223
+ sys2 = scor[sys2_ind];
224
+
225
+ alloc_SEG_LIST(seg_l,*max_seg);
226
+
227
+ for (spk1=0;spk1 < sys1->num_grp; spk1++){ /* for all speaker sys1 */
228
+ /**** find the matching speaker */
229
+ for (spk2=0;spk2 < sys2->num_grp; spk2++)
230
+ if (strcmp(sys1->grp[spk1].name, sys2->grp[spk2].name) == 0)
231
+ break;
232
+ /**** the the speakers match, start on the sentences */
233
+ if (spk2 != sys2->num_grp){
234
+ /**** for all sents in sys1,spkr1 */
235
+ for (snt1 = 0; snt1 < sys1->grp[spk1].num_path; snt1++){
236
+ /**** for all sents in sys2,spkr2 */
237
+ for (snt2 = 0; snt2 < sys2->grp[spk2].num_path; snt2++)
238
+ /**** if the sentences are the same, compare them */
239
+ if(strcmp(sys1->grp[spk1].path[snt1]->id,
240
+ sys2->grp[spk2].path[snt2]->id) == 0){
241
+ test_comp_sents(sys1->grp[spk1].path[snt1],
242
+ sys2->grp[spk2].path[snt2],
243
+ &seg_l,num_seg, max_seg, min_num_good);
244
+ sent_cnt++;
245
+ break;
246
+ }
247
+ }
248
+ } else {
249
+ fprintf(stderr,"Warning: Speaker %s is in system %s but not system %s\n",
250
+ sys1->grp[spk1].name,sys1->title,sys2->title);
251
+ }
252
+ }
253
+ /* calculate the percentages of errors for both systems and print */
254
+ /* a report if verbose == TRUE */
255
+ evaluate_SEG(sys1->title, sys2->title,seg_l,num_seg,sent_cnt,min_num_good,
256
+ sys1_pct,sys2_pct,seg_per_sent,verbose,fp);
257
+
258
+ alloc_singZ(err_diff,*max_seg,int,0);
259
+
260
+ /* calc an arr with the difference in the errors for each segment */
261
+ for (i=0;i<*num_seg;i++)
262
+ err_diff[i] = seg_hyp1(seg_l,i) - seg_hyp2(seg_l,i);
263
+
264
+ calc_mean_var_std_dev_Zstat(err_diff,*num_seg,
265
+ &mean,&variance,&std_dev,&median,Z_stat);
266
+ /* Special output routine */
267
+ if (verbose){
268
+ fprintf(fp,"MTCH_PR_RESULTS (systems: %s %s) (# segs: %d) "
269
+ "(Seg per Sent: %5.3f) ",
270
+ sys1->title,sys2->title,*num_seg,
271
+ *seg_per_sent);
272
+ fprintf(fp,"(%% Error: %5.2f %5.2f) (mean: %5.3f) (std dev: %5.3f) "
273
+ "(Z Stat: %5.3f) (Stat Diff: %s)\n",
274
+ *sys1_pct,*sys2_pct,mean,std_dev,*Z_stat,
275
+ (analyze_Z_score(sys1,sys2,mean,variance,std_dev,
276
+ *Z_stat,SILENT) == NO_DIFF) ? "No" : "Yes");
277
+ }
278
+
279
+ free_singarr(err_diff,int);
280
+ free_SEG_LIST(seg_l,*max_seg);
281
+ *conf = 1.0 - (2.0 * (normprob((double) (fabs(*Z_stat))) - 0.50));
282
+
283
+ return(analyze_Z_score(sys1,sys2,mean,variance,std_dev,*Z_stat,SILENT));
284
+ }
285
+
286
+ /**********************************************************************/
287
+ /* this procedure calculates the percentages of errors for each */
288
+ /* systems segments, if verbose == TRUE then a report is printed */
289
+ /* to stdout for looking at segment counts */
290
+ /**********************************************************************/
291
+ void evaluate_SEG(char *sys1_str, char *sys2_str, SEG **seg_l, int *num_seg, int sent_cnt, int min_good, double *s1_pct, double *s2_pct, double *seg_per_sent, int verbose,FILE *fp)
292
+ {
293
+ int i, tot_ref=0, tot_err_h1=0, tot_err_h2=0;
294
+
295
+ /* calc the pcts */
296
+ for (i=0;i<*num_seg;i++){
297
+ tot_ref += seg_ref(seg_l,i);
298
+ tot_err_h1 += seg_hyp1(seg_l,i);
299
+ tot_err_h2 += seg_hyp2(seg_l,i);
300
+ }
301
+ (*s1_pct) = pct(tot_err_h1,tot_ref);
302
+ (*s2_pct) = pct(tot_err_h2,tot_ref);
303
+ (*seg_per_sent) = (double)(*num_seg) / (double)sent_cnt;
304
+
305
+ /* if needed, print the systems segmentation reports */
306
+ if (verbose){
307
+ fprintf(fp," SEGMENTATION REPORT FOR SYSTEMS\n");
308
+ fprintf(fp," %4s and %4s\n",sys1_str, sys2_str);
309
+ fprintf(fp,"Minimum Number of Correct Boundary words %1d\n\n",min_good);
310
+ fprintf(fp," Number of Segments %2d, %5.3f per sentence\n",*num_seg,
311
+ (*seg_per_sent));
312
+ fprintf(fp," Number of Sentences %2d\n\n",sent_cnt);
313
+ fprintf(fp," # Ref wrds Err %4s Err %4s\n",sys1_str, sys2_str);
314
+ fprintf(fp,"---------------------------------------\n");
315
+ if (FALSE){
316
+ for (i=0;i<*num_seg;i++)
317
+ fprintf(fp," %4d %4d %4d\n",
318
+ seg_ref(seg_l,i),seg_hyp1(seg_l,i),seg_hyp2(seg_l,i));
319
+ fprintf(fp,"---------------------------------------\n");
320
+ }
321
+ fprintf(fp,"Totals %4d %4d %4d\n\n",
322
+ tot_ref,tot_err_h1,tot_err_h2);
323
+ fprintf(fp,"Pct err %5.1f%% %5.1f%%\n\n",
324
+ *s1_pct,*s2_pct);
325
+ fprintf(fp,"\n\n\n");
326
+
327
+ /* do a McNermar-style anaylsys */
328
+ /* first calc the matrix */
329
+ {
330
+ int **table=NULL, ans; double mcn_conf=0.0;
331
+ alloc_2dimZ(table,2,2,int,0);
332
+ for (i=0;i<*num_seg;i++){
333
+ if (seg_hyp1(seg_l,i) == 0 && seg_hyp2(seg_l,i) == 0 &&
334
+ seg_ref(seg_l,i) == 0){
335
+ table[0][0] ++; /* THIS WILL NEVER HAPPEN */
336
+ fprintf(stderr,"Warning: MPESM test identified a correct/correct segment- %d\n",i);
337
+ }
338
+ else if (seg_hyp1(seg_l,i) > 0 && seg_hyp2(seg_l,i) == 0)
339
+ table[1][0] ++;
340
+ else if (seg_hyp1(seg_l,i) == 0 && seg_hyp2(seg_l,i) > 0)
341
+ table[0][1] ++;
342
+ else
343
+ table[1][1] ++;
344
+ }
345
+ ans = do_McNemar(table,sys1_str,sys2_str,verbose,fp,&mcn_conf);
346
+
347
+ free_2dimarr(table,2,int);
348
+ }
349
+ }
350
+ if (0) { int i;
351
+ fprintf(fp,"Segment size Report\n");
352
+ for (i=0;i<*num_seg;i++){
353
+ fprintf(fp, " Segment: #ref=%d sys1Err=%d sys2Err=%d errDiff=%d\n",
354
+ seg_ref(seg_l,i), seg_hyp1(seg_l,i), seg_hyp2(seg_l,i),abs(seg_hyp1(seg_l,i) - seg_hyp2(seg_l,i)));
355
+ }
356
+ }
357
+ }
358
+
359
+
360
+ /**********************************************************************/
361
+ /* this function returns whether or not the Z_stat is outside the */
362
+ /* range of significance, if needed, a verbose report is printed */
363
+ /**********************************************************************/
364
+ int analyze_Z_score(SCORES *sys1, SCORES *sys2, double mean, double variance, double std_dev, double Z_stat, int verbose)
365
+ {
366
+ int eval;
367
+ char pad = '\0';
368
+
369
+ if (verbose){
370
+ printf("\n%s\t Analysis of matched pairs comparison\n\n",&pad);
371
+ printf("%s\t\t\t Comparing %s and %s\n\n",&pad,
372
+ sys1->title, sys2->title);
373
+ printf("%s\t H : means of sentence segment errors are equal.\n",&pad);
374
+ printf("%s\t 0\n\n",&pad);
375
+ eval = print_Z_analysis(Z_stat);
376
+ }
377
+ else
378
+ eval = Z_pass(Z_stat);
379
+ /* if the mean is less then we want the sys1 index to be the winner */
380
+ if (mean < 0.0)
381
+ eval *= (-1);
382
+ return(eval);
383
+ }
384
+
385
+ /**********************************************************************/
386
+ /* this procedure tries to break up sentences into segments and then*/
387
+ /* counts and stores the segment errors and size for later */
388
+ /* processing. The algorithm is a modified state transition graph */
389
+ /* that looks like this: */
390
+ /* */
391
+ /* the beginning state is b: */
392
+ /* corr means both sentences have the current word correct: */
393
+ /* error means at least one sentence had an error: */
394
+ /* _ */
395
+ /* / \ corr */
396
+ /* v / */
397
+ /* b <--------------. */
398
+ /* | | */
399
+ /* | error | */
400
+ /* | | */
401
+ /* V | */
402
+ /* ,-------------------> e<-. error | */
403
+ /* | |\_/ | */
404
+ /* | | | */
405
+ /* | ,---------> | good | */
406
+ /* | | V | */
407
+ /* | | if #good == min_good | */
408
+ /* error| corr| then store the segment ---' */
409
+ /* | | | */
410
+ /* | | V */
411
+ /* | `---------- g */
412
+ /* | | */
413
+ /* | | */
414
+ /* `---------------------' */
415
+ /* Modified: Nov 10, 1994 */
416
+ /* The synchronization between reference strings is lost if altern- */
417
+ /* ation is use in the reference strings. To correct the problem, */
418
+ /* code was added to re-sync the reference strings if needed. */
419
+ /* if the sync passes, the state is modified to dependent in the */
420
+ /* words skipped to for re-synchronization. */
421
+ /**********************************************************************/
422
+ void test_comp_sents(PATH *snt1, PATH *snt2, SEG ***seg_l, int *num_seg, int *max_seg, int min_good)
423
+ {
424
+ int ind1=0, ind2=0, eog1, eog2, state, num_good=0, dbg = 0;
425
+
426
+ eog1 = eog2 = 0;
427
+ state = 'b';
428
+
429
+ if (dbg){
430
+ printf("--------------------------------------------------\n");
431
+ printf(" number of adjacent good words %d\n\n",min_good);
432
+ PATH_print(snt1,stdout,100);
433
+ PATH_print(snt2,stdout,100);
434
+ }
435
+ while (ind1 < snt1->num){
436
+ if (dbg) printf("top of loop: state: %c ind1=%d ind2=%d\n",
437
+ state,ind1,ind2);
438
+ /* if either sent has an insertion mark it and goto state 'e' */
439
+ while ((ind1 < snt1->num) && snt1->pset[ind1].eval == P_INS)
440
+ ind1++, state = 'e';
441
+ while ((ind2 < snt2->num) && snt2->pset[ind2].eval == P_INS)
442
+ ind2++, state = 'e';
443
+ if (dbg) printf(" rm insert: state: %c ind1=%d ind2=%d\n",
444
+ state,ind1,ind2);
445
+ /* Check to see if there is a synchony error, and fix it ONLY */
446
+ /* if the evaluation of the words are different */
447
+ if (((ind1 < snt1->num && snt1->pset[ind1].a_ptr == NULL) ^
448
+ (ind2 < snt2->num && snt2->pset[ind2].a_ptr == NULL)) ||
449
+ ((ind1 < snt1->num && ind2 < snt2->num) &&
450
+ (strcmp(snt1->pset[ind1].a_ptr,snt2->pset[ind2].a_ptr) != 0) &&
451
+ (snt1->pset[ind1].eval != snt2->pset[ind2].eval))){
452
+
453
+ int i1=ind1, i2=ind2, synched=FALSE;
454
+ if (dbg) printf(" Warning: Reference words out of alignment\n");
455
+ if (dbg) printf(" Attempting to correct\n");
456
+ /* the algorithm: trace the following network in a depth first */
457
+ /* manner until the first synchronization occurs: */
458
+ /* Where A1 is the ref word s_ref_wrd(snt1,i1) . . . */
459
+ /* A1 A2 A3 A4 || A1 A2 A3 A4 || A1 A2 A3 A4 */
460
+ /* | \ || /| \ || ____//| \ */
461
+ /* | \ || / | \ || / / | \ */
462
+ /* B1 B2 B3 B4 || B1 B2 B3 B4 || B1 B2 B3 B4 */
463
+ while (i1 < snt1->num && !synched){
464
+ if (dbg) printf(" Starting at %d - %d\n",i1,i2);
465
+ while (i2 < snt2->num &&
466
+ (i2 <= (ind2+1+(i1-ind1))) && !synched){
467
+ if (dbg) printf(" compare %d to %d ",i1,i2);
468
+ if (strcmp(snt1->pset[i1].a_ptr,snt2->pset[i2].a_ptr) != 0)
469
+ synched = TRUE;
470
+ if (!synched) {
471
+ if (dbg) printf("Not synched\n");
472
+ i2++;
473
+ } else
474
+ if (dbg) printf("Synched\n");
475
+ }
476
+ if (!synched)
477
+ i1++;
478
+ }
479
+ if (!synched) {
480
+ if (dbg) printf(" I FAILED to synchronize, I'm sorry\n");
481
+ } else {
482
+ char tstate = state;
483
+ int ii1, ii2;
484
+ for (ii1 = ind1; ii1 <= i1; ii1++)
485
+ if (snt1->pset[ii1].eval != P_CORR) state = 'e';
486
+ for (ii2 = ind2; ii2 <= i2; ii2++)
487
+ if (snt2->pset[ii2].eval != P_CORR) state = 'e';
488
+ ind1 = i1; ind2 = i2;
489
+ if (dbg) {
490
+ printf(" Synch WORKED, at %d - %d\n",ind1,ind2);
491
+ printf(" State was '%c' now '%c'\n",tstate,state);
492
+ }
493
+ }
494
+ }
495
+ switch (state){
496
+ case 'b':
497
+ /* this state means we haven't found any errors yet */
498
+ /* if both corr, mark the end of the good(eog) for each sent*/
499
+ if (ind1 < snt1->num && snt1->pset[ind1].eval == P_CORR &&
500
+ ind2 < snt2->num && snt2->pset[ind2].eval == P_CORR)
501
+ eog1 = ind1, eog2 = ind2;
502
+ else
503
+ state = 'e';
504
+ break;
505
+ case 'e':
506
+ /* if both are correct, then check to see if the num_good */
507
+ /* equals the minimum if it is mark the seg and goto 'b' */
508
+ if (ind1 < snt1->num && snt1->pset[ind1].eval == P_CORR &&
509
+ ind2 < snt2->num && snt2->pset[ind2].eval == P_CORR) {
510
+ num_good = 1;
511
+ if (num_good == min_good){
512
+ if (dbg) printf(" segment: snt1:%d-%d snt2:%d-%d\n",
513
+ eog1-(min_good-1),ind1,eog2-(min_good-1),ind2);
514
+ count_seg(snt1,snt2,eog1-(min_good-1),
515
+ eog2-(min_good-1),ind1,ind2,
516
+ seg_l, num_seg, max_seg, dbg);
517
+ eog1 = ind1, eog2 = ind2, state = 'b';
518
+ }
519
+ else
520
+ state = 'g';
521
+ }
522
+ break;
523
+ case 'g':
524
+ /* count the good words until the minimum number is found*/
525
+ if (ind1 < snt1->num && snt1->pset[ind1].eval == P_CORR &&
526
+ ind2 < snt2->num && snt2->pset[ind2].eval == P_CORR){
527
+ num_good++;
528
+ if (num_good == min_good){
529
+ if (dbg) {
530
+ printf(" segment: snt1:%d-%d snt2:%d-%d\n",
531
+ eog1-(min_good-1),ind1,eog2-(min_good-1),ind2);
532
+ }
533
+ count_seg(snt1,snt2,eog1-(min_good-1),
534
+ eog2-(min_good-1),ind1,ind2,seg_l,num_seg,
535
+ max_seg,dbg);
536
+ eog1 = ind1, eog2 = ind2, state = 'b';
537
+ }
538
+ else
539
+ state = 'g';
540
+ }
541
+ /* an error was found before the num_good == min_good */
542
+ else
543
+ state = 'e';
544
+ break;
545
+ }
546
+
547
+ if (ind1 < snt1->num) ind1++;
548
+ if (ind2 < snt2->num) ind2++;
549
+ if (dbg) printf("end of loop: state: %c ind1=%d ind2=%d\n\n",state,ind1,ind2);
550
+ }
551
+ if (dbg) printf( "outsid loop: state: %c ind1=%d ind2=%d\n\n",state,ind1,ind2);
552
+ /* if the state is anything but 'b' then the end of the sentence ends */
553
+ /* the segment */
554
+ if (state != 'b' || (state == 'b' && snt2->num > ind2)){
555
+ if (dbg) {
556
+ printf(" segment: snt1:%d-%d snt2:%d-%d\n",
557
+ eog1-(min_good-1),snt1->num-1,eog2-(min_good-1),snt2->num-1);
558
+ }
559
+ count_seg(snt1,snt2,eog1-(min_good-1), eog2-(min_good-1),snt1->num-1,
560
+ snt2->num-1,seg_l,num_seg,max_seg,dbg);
561
+ }
562
+ }
563
+
564
+ /**********************************************************************/
565
+ /* this procedure only stores the errors and reference words in */
566
+ /* the segment then it stores the info in a list for segments */
567
+ /**********************************************************************/
568
+ void count_seg(PATH *snt1, PATH *snt2, int beg1, int beg2, int end1, int end2, SEG ***seg_l, int *num_seg, int *max_seg, int dbg)
569
+ {
570
+ /* static char *ref_str=NULL, **hyp_strs;*/
571
+ int err1, err2, ref1, ref2;
572
+
573
+ /* do bounds checking, if indexes are < 0 */
574
+ if (beg1 < 0) beg1 = 0;
575
+ if (beg2 < 0) beg2 = 0;
576
+
577
+ if (*num_seg >= *max_seg)
578
+ expand_SEG_LIST(*seg_l,*num_seg,*max_seg);
579
+
580
+ seg_count(snt1,beg1,end1,&err1,&ref1);
581
+ seg_count(snt2,beg2,end2,&err2,&ref2);
582
+
583
+ seg_ref((*seg_l),*num_seg) = (ref1 + ref2)/2;
584
+ seg_hyp1((*seg_l),*num_seg) = err1;
585
+ seg_hyp2((*seg_l),*num_seg) = err2;
586
+
587
+ if (dbg)
588
+ printf("Count Segment: segment# %3d: sys1=[beg=%d,end=%d,ref=%d,err=%d] sys2=[beg=%d,end=%d,ref=%d,err=%d]\n",
589
+ *num_seg,beg1,end1,ref1,err1,beg2,end2,ref2,err2);
590
+
591
+ if (err1 == 0 && err2 == 0){
592
+ fprintf(scfp,"Warning: MAPSSWE segmentation produced a segment with"
593
+ " errors\n ignoring segment\n");
594
+ }
595
+
596
+ /* print the sentence segments to stdout */
597
+ if (dbg){
598
+ if (ref1 != ref2){
599
+ printf("***** Reference Counts Not Equal\n");
600
+ printf("Segment# %3d: #ref %1d (%d+%d)/2\n",
601
+ *num_seg,(ref1+ref2)/2,ref1,ref2);
602
+ } else
603
+ printf("Segment# %3d: #ref %1d\n",*num_seg,ref1);
604
+
605
+ printf(" #Err. %2d\n",err1);
606
+ PATH_n_print(snt1, stdout, beg1, end1+1, 100);
607
+
608
+ printf(" #Err. %2d\n",err2);
609
+ PATH_n_print(snt2, stdout, beg2, end2+1, 100);
610
+ printf("\n\n");
611
+ }
612
+ if (! (err1 == 0 && err2 == 0))
613
+ (*num_seg)++;
614
+ }
615
+
616
+ /**********************************************************************/
617
+ /* this routine counts the errors and ref words in a segment */
618
+ /**********************************************************************/
619
+ void seg_count(PATH *snt, int from, int to, int *err, int *ref)
620
+ {
621
+ int i;
622
+
623
+ *err = *ref = 0;
624
+ for (i=from;i<= to;i++){
625
+ if (snt->pset[i].eval != P_CORR)
626
+ (*err)++;
627
+ if (snt->pset[i].eval != P_INS)
628
+ (*ref)++;
629
+ }
630
+ }
631
+
632
+ /**********************************************************************/
633
+ /* when the average segment analysis is ran, this procedure prints */
634
+ /* the report, for each number of minimum good words. this report */
635
+ /* prints the average number of segments per sentence for each */
636
+ /* number of buffer words (min_good) */
637
+ /**********************************************************************/
638
+ void print_sent_seg_averaged_analysis(SCORES *scor[], int nscor, double ***seg_per_sent, char *tname)
639
+ {
640
+ int sys1,sys2,num_g,num_comp;
641
+ double tot_sps;
642
+ char pad[FULL_SCREEN];
643
+ char *sub_title="Average Number of Segments Per Sentence Report for";
644
+ char *sub_title1="Changing Numbers of Buffer Words";
645
+
646
+ set_pad_cent_n(pad,strlen(sub_title), FULL_SCREEN);
647
+ printf("%s%s\n",pad,sub_title);
648
+ set_pad_cent_n(pad,strlen(sub_title1), FULL_SCREEN);
649
+ printf("%s%s\n",pad,sub_title1);
650
+ if (*tname != '\0'){
651
+ set_pad(pad,tname, FULL_SCREEN);
652
+ printf("%s%s\n",pad,tname);
653
+ }
654
+ printf("\n\n");
655
+
656
+ set_pad(pad,"--------------------------------", FULL_SCREEN);
657
+ printf("%s--------------------------------\n",pad);
658
+ printf("%s| Num Buf | Ave Seg/Sent |\n",pad);
659
+ printf("%s|-------------+----------------|\n",pad);
660
+ for (num_g=0; num_g<MAX_SEG_ANAL; num_g++){
661
+ num_comp = tot_sps = 0;
662
+ for (sys1=0;sys1<nscor;sys1++)
663
+ for (sys2=sys1+1;sys2<nscor;sys2++)
664
+ num_comp++, tot_sps+= seg_per_sent[num_g][sys1][sys2];
665
+ printf("%s| %2d | %5.3f |\n",
666
+ pad,num_g+1,(tot_sps/num_comp));
667
+ }
668
+ printf("%s--------------------------------\n",pad);
669
+ form_feed(stdout);
670
+ }
671
+
672
+ /**********************************************************************/
673
+ /* when the long segment analysis is ran, this procedure prints */
674
+ /* the report, for each number of minimum good words. this report */
675
+ /* prints the number of segments per sentence for each system */
676
+ /* by system comparison */
677
+ /**********************************************************************/
678
+ void print_sent_seg_long_analysis(SCORES *scor[], int nscor, double ***seg_per_sent, char *tname)
679
+ {
680
+ int i,j,k;
681
+ char pad[FULL_SCREEN];
682
+ char *sub_title="Number of Segments Per Sentence Report for Changing";
683
+ char *sub_title1="Numbers of Buffer Words";
684
+
685
+ set_pad_cent_n(pad,strlen(sub_title), FULL_SCREEN);
686
+ printf("%s%s\n",pad,sub_title);
687
+ set_pad_cent_n(pad,strlen(sub_title1), FULL_SCREEN);
688
+ printf("%s%s\n",pad,sub_title1);
689
+ if (*tname != '\0'){
690
+ set_pad(pad,tname, FULL_SCREEN);
691
+ printf("%s%s\n",pad,tname);
692
+ }
693
+ printf("\n");
694
+
695
+ set_pad_cent_n(pad,(nscor+1) * 15, FULL_SCREEN);
696
+ printf("\n%s|-------------",pad);
697
+ for (k=0;k<nscor;k++)
698
+ printf("%13s","--------------");
699
+ printf("|\n");
700
+
701
+ printf("%s| |",pad);
702
+ for (i=0;i<nscor;i++)
703
+ printf(" %4s |",scor[i]->title);
704
+ printf("\n");
705
+
706
+ for (i=0;i<nscor;i++){
707
+ printf("%s|-------------",pad);
708
+ for (k=0;k<nscor;k++)
709
+ printf("+-------------");
710
+ printf("|\n");
711
+ printf("%s| %4s 0 |",pad,scor[i]->title);
712
+ for (j=0;j<nscor;j++)
713
+ if (j > i)
714
+ printf(" %5.3f |",seg_per_sent[0][i][j]);
715
+ else
716
+ printf(" |");
717
+ printf("\n");
718
+ if (MAX_SEG_ANAL >=2)
719
+ for (k=1; k<MAX_SEG_ANAL; k++){
720
+ printf("%s| %2d |",pad,k);
721
+ for (j=0;j<nscor;j++)
722
+ if (j > i)
723
+ printf(" %5.3f |",seg_per_sent[k][i][j]);
724
+ else
725
+ printf(" |");
726
+ printf("\n");
727
+ }
728
+ }
729
+ printf("%s|-------------",pad);
730
+ for (k=0;k<nscor;k++)
731
+ printf("%11s","--------------");
732
+ printf("|\n");
733
+ form_feed(stdout);
734
+ }
735
+
736
+ /**********************************************************************/
737
+ /* this procedure prints the Matched pairs report for a single */
738
+ /* min_num_good length. */
739
+ /**********************************************************************/
740
+ void print_compare_matrix_for_sys(SCORES *scor[], int nscor, int **winner, char *matrix_name, char *tname, char *v_desc, double **sys1_pct_arr, double **sys2_pct_arr, int **num_seg, double **Z_stat, int min_num_good, FILE *fp)
741
+ {
742
+ int i,j,k,block_size,sys,max_name_len=0;
743
+ int hyphen_len=49, space_len=49;
744
+ char pad[FULL_SCREEN], hyphens[50], spaces[50], sysname_fmt[40];
745
+ char *min_good_title="Minimum Number of Correct Boundary words";
746
+
747
+ /* init the hyphens and spaces array */
748
+ for (i=0; i<hyphen_len; i++){
749
+ hyphens[i]='-';
750
+ spaces[i]=' ';
751
+ }
752
+ hyphens[hyphen_len]='\0'; spaces[space_len]='\0';
753
+ /* find the largest system length */
754
+ for (sys=0;sys<nscor;sys++)
755
+ if ((i=strlen(scor[sys]->title)) > max_name_len)
756
+ max_name_len = i;
757
+ block_size = (3+max_name_len);
758
+ sprintf(sysname_fmt," %%%ds |",max_name_len);
759
+
760
+ set_pad(pad,matrix_name, FULL_SCREEN);
761
+ fprintf(fp,"\n\n\n%s%s\n",pad,matrix_name);
762
+ if (*v_desc != '\0'){
763
+ set_pad(pad,v_desc, FULL_SCREEN);
764
+ fprintf(fp,"%s%s\n",pad,v_desc);
765
+ }
766
+ if (*tname != '\0'){
767
+
768
+
769
+ set_pad(pad,tname, FULL_SCREEN);
770
+ fprintf(fp,"%s%s\n",pad,tname);
771
+ }
772
+ set_pad_cent_n(pad,strlen(min_good_title)+2, FULL_SCREEN);
773
+ fprintf(fp,"%s%s %1d\n",pad,min_good_title,min_num_good);
774
+ fprintf(fp,"\n");
775
+
776
+ set_pad_cent_n(pad,(nscor+1) * block_size, FULL_SCREEN);
777
+ fprintf(fp,"\n%s|%s",pad,hyphens+hyphen_len-MIN(hyphen_len,(block_size-1)));
778
+ for (k=0;k<nscor;k++)
779
+ fprintf(fp,"%s",hyphens+hyphen_len-MIN(hyphen_len,block_size));
780
+ fprintf(fp,"|\n");
781
+
782
+ fprintf(fp,"%s|%s|",pad,spaces+space_len-MIN(space_len,(block_size-1)));
783
+ for (i=0;i<nscor;i++)
784
+ fprintf(fp,sysname_fmt,scor[i]->title);
785
+ fprintf(fp,"\n");
786
+
787
+ for (i=0;i<nscor;i++){
788
+ fprintf(fp,"%s|%s",pad,hyphens+hyphen_len-MIN(hyphen_len,(block_size-1)));
789
+ for (k=0;k<nscor;k++)
790
+ fprintf(fp,"+%s",hyphens+hyphen_len-MIN(hyphen_len,(block_size-1)));
791
+ fprintf(fp,"|\n");
792
+ fprintf(fp,"%s|",pad);
793
+ fprintf(fp,sysname_fmt,scor[i]->title);
794
+ for (j=0;j<nscor;j++){
795
+ char *name="";
796
+ int t=0;
797
+ if (j > i){
798
+ if (winner[i][j] == TEST_DIFF)
799
+ name=scor[j]->title;
800
+ else if (winner[i][j] == NO_DIFF)
801
+ name="same";
802
+ else
803
+ name=scor[i]->title;
804
+ t = (block_size-1-strlen(name))/2;
805
+ }
806
+ fprintf(fp,"%s%s%s|",spaces+space_len-MIN(space_len,t),name,
807
+ spaces+space_len-MIN(space_len,(block_size-1-strlen(name)-t)));
808
+ }
809
+ fprintf(fp,"\n");
810
+ #ifdef you_want_more_output
811
+ fprintf(fp,"%s| |",pad);
812
+ for (j=0;j<nscor;j++)
813
+ if (j > i)
814
+ fprintf(fp," %3d %6.2f |",num_seg[i][j],Z_stat[i][j]);
815
+ else
816
+ fprintf(fp," |");
817
+ fprintf(fp,"\n");
818
+ fprintf(fp,"%s| |",pad);
819
+ for (j=0;j<nscor;j++)
820
+ if (j > i)
821
+ fprintf(fp," %4.1f%% %4.1f%% |",sys1_pct_arr[i][j],
822
+ sys2_pct_arr[i][j]);
823
+ else
824
+ fprintf(fp," |");
825
+ fprintf(fp,"\n");
826
+ #endif
827
+ }
828
+ fprintf(fp,"%s|%s",pad,hyphens+hyphen_len-MIN(hyphen_len,(block_size-1)));
829
+ for (k=0;k<nscor;k++)
830
+ fprintf(fp,"%s",hyphens+hyphen_len-MIN(hyphen_len,block_size));
831
+ fprintf(fp,"|\n");
832
+ }
833
+
SCTK/src/sclite/net_adt.o ADDED
Binary file (43.1 kB). View file
 
SCTK/src/sclite/order.c ADDED
@@ -0,0 +1,277 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**********************************************************************/
2
+ /* */
3
+ /* FILENAME: order.c */
4
+ /* BY: Jonathan G. Fiscus */
5
+ /* NATIONAL INSTITUTE OF STANDARDS AND TECHNOLOGY */
6
+ /* SPEECH RECOGNITION GROUP */
7
+ /* */
8
+ /* DESC: this file contains routines to sort and rank */
9
+ /* various types of numeric arrays in INCREASING */
10
+ /* of DECREASING order */
11
+ /* */
12
+ /**********************************************************************/
13
+ #include "sctk.h"
14
+
15
+
16
+ /**********************************************************************/
17
+ /* qsort short comparison functions */
18
+ int qsort_short_cmp(const void *p, const void *p1);
19
+
20
+ int qsort_short_deccmp(const void *p, const void *p1);
21
+
22
+ static short *short_cmp_arr;
23
+ int qsort_short_cmp(const void *p, const void *p1){
24
+ return(short_cmp_arr[*((int *)p)] - short_cmp_arr[*((int *)p1)]);
25
+ }
26
+ int qsort_short_deccmp(const void *p, const void *p1){
27
+ return(short_cmp_arr[*((int *)p1)] - short_cmp_arr[*((int *)p)]);
28
+ }
29
+
30
+ /**********************************************************************/
31
+ /* qsort int comparison functions */
32
+ int qsort_int_cmp(const void *p, const void *p1);
33
+ int qsort_int_deccmp(const void *p, const void *p1);
34
+
35
+ static int *int_cmp_arr;
36
+ int qsort_int_cmp(const void *p, const void *p1){
37
+ return(int_cmp_arr[*((int *)p)] - int_cmp_arr[*((int *)p1)]);
38
+ }
39
+ int qsort_int_deccmp(const void *p, const void *p1){
40
+ return(int_cmp_arr[*((int *)p1)] - int_cmp_arr[*((int *)p)]);
41
+ }
42
+ int qsort_int_compare(const void *i, const void *j) {
43
+ return(*((int *)i) - *((int *)j));
44
+ }
45
+
46
+
47
+
48
+
49
+ /**********************************************************************/
50
+ /* qsort double comparison functions */
51
+ int qsort_double_cmp(const void *p, const void *p1);
52
+ int qsort_double_deccmp(const void *p, const void *p1);
53
+
54
+ static double *double_cmp_arr;
55
+ int qsort_double_cmp(const void *p, const void *p1){
56
+ double f = double_cmp_arr[*((int *)p)] - double_cmp_arr[*((int *)p1)];
57
+ return((f < 0.0) ? -1 : ((f > 0) ? 1 : 0));
58
+ }
59
+ int qsort_double_deccmp(const void *p, const void *p1){
60
+ double f = double_cmp_arr[*((int *)p1)] - double_cmp_arr[*((int *)p)];
61
+ return((f < 0.0) ? -1 : ((f > 0) ? 1 : 0));
62
+ }
63
+ int qsort_double_compare(const void *i, const void *j) {
64
+ double f = *((double *)i) - *((double *)j);
65
+ return((f < 0.0) ? -1 : ((f > 0) ? 1 : 0));
66
+ }
67
+
68
+ /**********************************************************************/
69
+ /* Sort a short array */
70
+ /* arr -> the short array */
71
+ /* ptr_arr -> an integer array of indexes into arr. */
72
+ /* using this array to index arr, sorts the arr */
73
+ /**********************************************************************/
74
+ void sort_short_arr(short int *arr, int num, int *ptr_arr, int order)
75
+ {
76
+ int j;
77
+ /* init the indexes to 1-n */
78
+ for (j=0;j<num;j++)
79
+ ptr_arr[j] = j;
80
+
81
+ short_cmp_arr = arr;
82
+ if (order == INCREASING)
83
+ qsort((void *)ptr_arr,num,sizeof(int),qsort_short_cmp);
84
+ else
85
+ qsort((void *)ptr_arr,num,sizeof(int),qsort_short_deccmp);
86
+ }
87
+
88
+
89
+ /**********************************************************************/
90
+ /* Sort a double array */
91
+ /* arr -> the double array */
92
+ /* ptr_arr -> an integer array of indexes into arr. */
93
+ /* using this array to index arr, sorts the arr */
94
+ /**********************************************************************/
95
+ void sort_double_arr(double *arr, int num, int *ptr_arr, int order)
96
+ {
97
+ int j;
98
+ /* init the indexes to 1-n */
99
+ for (j=0;j<num;j++)
100
+ ptr_arr[j] = j;
101
+
102
+ double_cmp_arr = arr;
103
+ if (order == INCREASING)
104
+ qsort((void *)ptr_arr,num,sizeof(int),qsort_double_cmp);
105
+ else
106
+ qsort((void *)ptr_arr,num,sizeof(int),qsort_double_deccmp);
107
+ }
108
+
109
+ /**********************************************************************/
110
+ /* Sort a int array */
111
+ /* arr -> the int array */
112
+ /* ptr_arr -> an integer array of indexes into arr. */
113
+ /* using this array to index arr, sorts the arr */
114
+ /**********************************************************************/
115
+ void sort_int_arr(int *arr, int num, int *ptr_arr, int order)
116
+ {
117
+ int j;
118
+ /* init the indexes to 1-n */
119
+ for (j=0;j<num;j++)
120
+ ptr_arr[j] = j;
121
+
122
+ int_cmp_arr = arr;
123
+ if (order == INCREASING)
124
+ qsort((void *)ptr_arr,num,sizeof(int),qsort_int_cmp);
125
+ else
126
+ qsort((void *)ptr_arr,num,sizeof(int),qsort_int_deccmp);
127
+ }
128
+
129
+ /**********************************************************************/
130
+ /* Sort an array strings. to access the results, a double */
131
+ /* indirection is needed. */
132
+ /* arr -> the 2 dimarr of chars */
133
+ /**********************************************************************/
134
+ void sort_strings_using_index(char **arr, int *ind, int num, int order)
135
+ {
136
+ int i, j, tmp;
137
+
138
+ for (i=0;i<num;i++)
139
+ ind[i] = i;
140
+
141
+ if (order == DECREASING){
142
+ for (j=num;j>0;j--){
143
+ for (i=0;i<j-1;i++)
144
+ if (strcmp(arr[ind[i]],arr[ind[i+1]]) < 0){
145
+ tmp = ind[i];
146
+ ind[i] = ind[i+1];
147
+ ind[i+1] = tmp;
148
+ }
149
+ }
150
+ }
151
+ else{
152
+ for (j=num;j>0;j--)
153
+ for (i=0;i<j-1;i++)
154
+ if (strcmp(arr[ind[i]],arr[ind[i+1]]) > 0){
155
+ tmp = ind[i];
156
+ ind[i] = ind[i+1];
157
+ ind[i+1] = tmp;
158
+ }
159
+ }
160
+ /* printf("sort debug\n");
161
+ for (i=0;i<num;i++)
162
+ printf(" %d arr[%d]-> %s \n",i,ind[i],arr[ind[i]]);*/
163
+
164
+ }
165
+
166
+ /**********************************************************************/
167
+ /* Sort an array strings in place */
168
+ /* arr -> the 2 dimarr of chars */
169
+ /**********************************************************************/
170
+ void sort_strings_in_place(char **arr, int num, int order)
171
+ {
172
+ int i, j;
173
+ char *tmp;
174
+
175
+ if (order == DECREASING){
176
+ for (j=num;j>0;j--){
177
+ for (i=0;i<j-1;i++)
178
+ if (strcmp(arr[i],arr[i+1]) < 0){
179
+ tmp = arr[i];
180
+ arr[i] = arr[i+1];
181
+ arr[i+1] = tmp;
182
+ }
183
+ }
184
+ }
185
+ else{
186
+ for (j=num;j>0;j--)
187
+ for (i=0;i<j-1;i++)
188
+ if (strcmp(arr[i],arr[i+1]) > 0){
189
+ tmp = arr[i];
190
+ arr[i] = arr[i+1];
191
+ arr[i+1] = tmp;
192
+ }
193
+ }
194
+ /* for (i=0;i<num;i++)
195
+ printf("%s ",arr[i]);
196
+ printf("\n");*/
197
+ }
198
+
199
+ /**********************************************************************/
200
+ /* Sort and rank an integer array */
201
+ /* arr -> the integer array */
202
+ /* ptr_arr -> an integer array of indexes into arr. */
203
+ /* using this array to index arr, sorts the arr */
204
+ /* rank_arr -> an array of mean ranks of the elements in arr */
205
+ /**********************************************************************/
206
+ void rank_int_arr(int *arr, int num, int *ptr_arr, double *rank_arr, int order)
207
+ {
208
+ int i, j, tmp, count;
209
+
210
+
211
+ sort_int_arr(arr, num, ptr_arr, order);
212
+
213
+ /* mean rank the short arr */
214
+ /* . . . the average of the ranks for duplicate numbers */
215
+ for (j=0;j<num;j++){
216
+ /* if the next number is = the the current number */
217
+ if ((j<num-1) && (arr[ptr_arr[j]] == arr[ptr_arr[j+1]])){
218
+ /* find the last duplicate number */
219
+ count = j;
220
+ while((count < num-1) &&
221
+ (arr[ptr_arr[count]] == arr[ptr_arr[count+1]])){
222
+ count++;
223
+ }
224
+ /* count the number of duplicates */
225
+ tmp = 0;
226
+ for (i=j;i<count+1;i++)
227
+ tmp+=i;
228
+ /* install the averages in all duplicates */
229
+ for (i=j;i<count+1;i++)
230
+ rank_arr[ptr_arr[i]] = (double)tmp/(double)(count+1-j) + 1.0;
231
+ /* go the the end of the duplicates */
232
+ j=i-1;
233
+ }
234
+ else{
235
+ /* no duplicates, use the index as the rank */
236
+ rank_arr[ptr_arr[j]] = (double)(j+1);
237
+ }
238
+ }
239
+ }
240
+
241
+ /**********************************************************************/
242
+ /* Sort and rank an double array */
243
+ /* arr -> the double array */
244
+ /* ptr_arr -> an integer array of indexes into arr. */
245
+ /* using this array to index arr, sorts the arr */
246
+ /* rank_arr -> an array of mean ranks of the elements in arr */
247
+ /* */
248
+ /* *** for comments, look up at sort_int_arr */
249
+ /* */
250
+ /**********************************************************************/
251
+ void rank_double_arr(double *arr, int num, int *ptr_arr, double *rank_arr, int order)
252
+ {
253
+ int i, j, tmp, count;
254
+
255
+ sort_double_arr(arr, num, ptr_arr, order);
256
+
257
+ for (j=0;j<num;j++){
258
+ if ((j<num-1) && (arr[ptr_arr[j]] == arr[ptr_arr[j+1]])){
259
+ count = j;
260
+ while((count < num-1) &&
261
+ (arr[ptr_arr[count]] == arr[ptr_arr[count+1]])){
262
+ count++;
263
+ }
264
+ tmp = 0;
265
+ for (i=j;i<count+1;i++)
266
+ tmp+=i;
267
+ for (i=j;i<count+1;i++)
268
+ rank_arr[ptr_arr[i]] = (double)tmp/(double)(count+1-j) + 1.0;
269
+ j=i-1;
270
+ }
271
+ else{
272
+ rank_arr[ptr_arr[j]] = (double)(j+1);
273
+ }
274
+ }
275
+ }
276
+
277
+
SCTK/src/sclite/order.o ADDED
Binary file (4.88 kB). View file
 
SCTK/src/sclite/pad.h ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ void init_pad_util PROTO((int pr_width)) ;
2
+ int pad_pr_width PROTO((void)) ;
3
+ void set_pad PROTO((char *pad, char *str, int max)) ;
4
+ void set_pad_n PROTO((char *pad, int n, int max)) ;
5
+ void set_pad_cent_n PROTO((char *pad, int len, int max)) ;
6
+ char *center PROTO((char *str, int len)) ;
7
+ void strncpy_pad PROTO((char *to, char *from, int len, int max, char chr)) ;
SCTK/src/sclite/sclite.c ADDED
@@ -0,0 +1,764 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #define MAIN
3
+ #include "sctk.h"
4
+
5
+ #define SCLITE_VERSION "2.10"
6
+
7
+ void do_exit(char *desc, char *prog, int ret);
8
+ void proc_args(int argc, char **argv, char *prog, char **rname, char **rfmt, char **hname, char **hfmt, int *nhyps, enum id_types *id_type, int *case_sens, int *outputs, char **title, int *feedback, int *linewidth, int *use_diff, char **out_dir, char **out_name,int *char_align, int *pipeout, int *pipein, int *infered_wordseg, char **lexicon, int *frag_correct, int *opt_del, int *inf_flags, int *stm2ctm_reduce, int *time_align, int *conf_outputs, int *left_to_right, char **wwl_file, char **lm_file);
9
+ int TEXT_set_lang_prof(char *lprof);
10
+
11
+ #define OUT_SUM 0x0001
12
+ #define OUT_RSUM 0x0002
13
+ #define OUT_PRALIGN 0x0004
14
+ #define OUT_LUR 0x0008
15
+ #define OUT_SGML 0x0010
16
+ #define OUT_STDOUT 0x0020
17
+ #define OUT_SENT 0x0040
18
+ #define OUT_SPKR 0x0080
19
+ #define OUT_DTL 0x0100
20
+ #define OUT_PRALIGN_FULL 0x0200
21
+ #define OUT_WWS 0x0400
22
+ #define OUT_NL_SGML 0x0800
23
+
24
+ #define CONF_OUT_NONE 0x0000
25
+ #define CONF_OUT_DET 0x0001
26
+ #define CONF_OUT_BHIST 0x0002
27
+ #define CONF_OUT_HIST 0x0004
28
+ #define CONF_OUT_SBHIST 0x0008
29
+
30
+ #define REDUCE_NOTHING 0x0000
31
+ #define REDUCE_REF_SEGMENTS 0x0001
32
+ #define REDUCE_HYP_WORDS 0x0002
33
+
34
+ char *usage = "%s: <OPTIONS>\n"
35
+ "sclite Version: " SCLITE_VERSION ", SCTK Version: " TK_VERSION "\n"
36
+ "Input Options:\n"
37
+ " -r reffile [ <rfmt> ]\n"
38
+ " Define the reference file, and it's format\n"
39
+ " -h hypfile [ <hfmt> <title> ]\n"
40
+ " Define the hypothesis file, it's format, and a 'title' used\n"
41
+ " for reports. The default title is 'hypfile'. This option\n"
42
+ " may be used more than once.\n"
43
+ " -i <ids> Set the utterance id type. (for transcript mode only)\n"
44
+ " -P Accept the piped input from another utility.\n"
45
+ " -e gb|euc|utf-8 [ case-conversion-localization ]\n"
46
+ " Interpret characters as GB, EUC, utf-8, or the default, 8-bit ASCII.\n"
47
+ " Optionally, case conversion localization can be set to either 'generic',\n"
48
+ " 'babel_turkish', or 'babel_vietnamese', 'ukranian'\n"
49
+ "Alignment Options:\n"
50
+ " -s Do Case-sensitive alignments.\n"
51
+ " -d Use GNU diff for alignments.\n"
52
+ " -c [ NOASCII DH ]\n"
53
+ " Do the alignment on characters not on words as usual by split-\n"
54
+ " ting words into chars. The optional argument NOASCII does not\n"
55
+ " split ASCII words and the optional arg. DH deletes hyphens from\n"
56
+ " both the ref and hyp before alingment. Exclusive with -d.\n"
57
+ " -L LM CMU-Cambridge SLM Language model file to use in alignment and scoring.\n"
58
+ " -S algo1 lexicon [ ASCIITOO ]\n"
59
+ " -S algo2 lexicon [ ASCIITOO ]\n"
60
+ " Instead of performing word alignments, infer the word segmenta-\n"
61
+ " tion using algo1 or algo2. See sclite(1) for algorithm details.\n"
62
+ " -F Score fragments as correct. Options -F and -d are exclusive.\n"
63
+ " -D Score words marked optionally deletable as correct if deleted.\n"
64
+ " Options -D and -d are exclusive.\n"
65
+ " -T Use time information, (if available), to calculated word-to-\n"
66
+ " word distances based on times. Options -F and -d are exlc.\n"
67
+ " -w wwl Perform Word-Weight Mediated alignments, using the WWL file 'wwl'.\n"
68
+ " IF wwl is 'unity' use weight 1.o for all words.\n"
69
+ " -m [ ref | hyp ]\n"
70
+ " Only used for scoring a hyp/ctm file, against a ref/stm file.\n"
71
+ " When the 'ref' option is used, reduce the reference segments\n"
72
+ " to time range of the hyp file's words. When the 'hyp' option\n"
73
+ " is used, reduce the hyp words to the time range of the ref\n"
74
+ " segments. The two may be used together. The argument -m\n"
75
+ " by itself defaults to '-m ref'. Exclusive with -d.\n"
76
+ "Output Options:\n"
77
+ " -O output_dir\n"
78
+ " Writes all output files into output_dir. Defaults to the\n"
79
+ " hypfile's directory.\n"
80
+ " -f level Defines feedback mode, default is 1\n"
81
+ " -l width Defines the line width.\n"
82
+ " -p Pipe the alignments to another sclite utility. Sets -f to 0.\n"
83
+ "Scoring Report Options:\n"
84
+ " -o [ sum | rsum | pralign | all | sgml | stdout | lur | snt | spk | \n"
85
+ " dtl | prf | wws | nl.sgml | none ]\n"
86
+ " Defines the output reports. Default: 'sum stdout'\n"
87
+ " -C [ det | bhist | sbhist | hist | none ] \n"
88
+ " Defines the output formats for analysis of confidence scores.\n"
89
+ " Default: 'none'\n"
90
+ " -n name Writes all outputs using 'name' as a root filename instead of\n"
91
+ " 'hypfile'. For multiple hypothesis files, the root filename\n"
92
+ " is 'name'.'hypfile'\n";
93
+
94
+ #define MAX_HYPS 40
95
+
96
+ int main(int argc, char **argv){
97
+ char *prog = "sclite";
98
+ char *refname, *hypname[MAX_HYPS], *reffmt, *hypfmt[MAX_HYPS],
99
+ *title[MAX_HYPS];
100
+ char *out_dir, *out_name;
101
+ char *wwl_file;
102
+ enum id_types id_type;
103
+ int errors = 0;
104
+ int num_hyps;
105
+ int linewidth;
106
+ int outputs;
107
+ int conf_outputs;
108
+ int feedback;
109
+ int use_diff;
110
+ SCORES *scor[MAX_HYPS];
111
+ int case_sense, nsc;
112
+ int char_align;
113
+ int pipeout;
114
+ int pipein;
115
+ int num_piped;
116
+ int nh;
117
+ char *hroot;
118
+ int hdirLen = FILENAME_MAX;
119
+ int outrootLen = FILENAME_MAX;
120
+ TEXT *hdir, *outroot;
121
+ int infered_wordseg;
122
+ char *lexicon;
123
+ int frag_correct;
124
+ int opt_del;
125
+ int inf_flags;
126
+ int stm2ctm_reduce;
127
+ int time_align;
128
+ int left_to_right;
129
+ WWL *wwl = (WWL *)0;
130
+ char *lm_file;
131
+
132
+ alloc_singZ(hdir, hdirLen, TEXT, NULL_TEXT);
133
+ alloc_singZ(outroot, outrootLen, TEXT, NULL_TEXT);
134
+
135
+ #ifdef LM_ALIGN
136
+ /* ng_t ng; */
137
+
138
+ #endif
139
+
140
+ db = db_level = 0;
141
+ proc_args(argc, argv, prog, &refname, &reffmt, hypname, hypfmt,
142
+ &num_hyps, &id_type, &case_sense,&outputs,title,&feedback,
143
+ &linewidth,&use_diff,&out_dir,&out_name,&char_align,&pipeout,
144
+ &pipein, &infered_wordseg, &lexicon, &frag_correct, &opt_del,
145
+ &inf_flags, &stm2ctm_reduce, &time_align, &conf_outputs,
146
+ &left_to_right, &wwl_file, &lm_file);
147
+
148
+ if (feedback > 0) printf("sclite: " SCLITE_VERSION
149
+ " TK Version " TK_VERSION"\n");
150
+
151
+ if (pipein){
152
+ if (feedback >= 1) printf("Loading Piped input. . . ");
153
+ num_piped = 0;
154
+ if (!load_SCORES_sgml(stdin,scor,&num_piped,MAX_HYPS)){
155
+ fprintf(scfp,"load_SCORES_sgml Failed\n");
156
+ exit(1);
157
+ }
158
+ if (feedback >= 1) printf("%d systems loaded.\n",num_piped);
159
+ } else
160
+ num_piped = 0;
161
+
162
+ if (wwl_file != (char *)0){
163
+ if (feedback >= 1)
164
+ printf("Loading WWL file '%s'\n",wwl_file);
165
+ if (load_WWL(&wwl,(TEXT *)wwl_file) != 0){
166
+ fprintf(stderr,"Error: Unable to read WWL file '%s'\n",wwl_file);
167
+ exit(1);
168
+ }
169
+ wwl->curw = 0;
170
+ }
171
+
172
+ for (nsc=0; nsc<num_hyps + num_piped; nsc++){
173
+ if (nsc >= num_piped){
174
+ nh = nsc - num_piped;
175
+ if (feedback >= 1)
176
+ printf("Begin alignment of Ref File: '%s' and %s: '%s'\n",
177
+ refname, "Hyp File", hypname[nh]);
178
+
179
+ /* Set up the output root name */
180
+ if ((hroot = strrchr(hypname[nh],'/')) != NULL){
181
+ if (hroot-hypname[nh] + 1 > hdirLen){
182
+ expand_singarr_to_size(hdir,(hroot-hypname[nh]),hdirLen,hroot-hypname[nh]+1,TEXT);
183
+ }
184
+ TEXT_strBcpy((TEXT *)hdir,(TEXT *)hypname[nh],hroot-hypname[nh]);
185
+ hroot++;
186
+ } else {
187
+ hroot = hypname[nh];
188
+ TEXT_strcpy(hdir,(TEXT *)".");
189
+ }
190
+
191
+ { char *name;
192
+ if ((out_dir != (char *)0) ||
193
+ TEXT_strcmp(((out_dir != (char *)0) ? (TEXT *)out_dir : (TEXT *)hdir),(TEXT *)".") != 0)
194
+ name = rsprintf("%s/%s",((out_dir != (char *)0) ? out_dir : (char *)hdir),
195
+ (out_name != (char *)0) ? out_name : hroot);
196
+ else
197
+ name = rsprintf("%s",(out_name != (char *)0) ? out_name : hroot);
198
+ if (outrootLen < TEXT_strlen((TEXT *)name)+1){
199
+ expand_singarr(outroot,TEXT_strlen((TEXT *)name),outrootLen,1.5,TEXT);
200
+ }
201
+ TEXT_strcpy(outroot, (TEXT *)name);
202
+ }
203
+ if (strcmp(reffmt,"trn") == 0 && strcmp(hypfmt[nh],"trn") == 0)
204
+ if (!use_diff)
205
+ scor[nh]=align_trans_mode_dp(refname,hypname[nh],title[nh],
206
+ 1,case_sense,feedback,
207
+ char_align,id_type,
208
+ infered_wordseg, lexicon,
209
+ frag_correct, opt_del,
210
+ inf_flags, wwl, lm_file);
211
+ else
212
+ scor[nh]=align_trans_mode_diff(refname,hypname[nh],
213
+ title[nh],1,case_sense,
214
+ feedback,id_type);
215
+ else if (strcmp(reffmt,"stm")== 0 && strcmp(hypfmt[nh],"ctm") == 0)
216
+ if (!use_diff)
217
+ scor[nh]=align_ctm_to_stm_dp(refname,hypname[nh],title[nh],
218
+ 1, case_sense,feedback,
219
+ char_align,id_type,
220
+ infered_wordseg, lexicon,
221
+ frag_correct, opt_del,
222
+ inf_flags,
223
+ BF_isSET(stm2ctm_reduce,REDUCE_REF_SEGMENTS),
224
+ BF_isSET(stm2ctm_reduce,REDUCE_HYP_WORDS),
225
+ left_to_right, wwl, lm_file);
226
+ else {
227
+ if (left_to_right)
228
+ scor[nh]=align_ctm_to_stm_diff(refname, hypname[nh],
229
+ title[nh],1,case_sense,
230
+ feedback,id_type);
231
+ else {
232
+ fprintf(scfp,"Error: can't perform diff alignments on "
233
+ "right-to-left data\n");
234
+ exit(1);
235
+ }
236
+ }
237
+ else if (strcmp(reffmt,"ctm")== 0 && strcmp(hypfmt[nh],"ctm") == 0)
238
+ scor[nh]=align_ctm_to_ctm(hypname[nh], refname, title[nh],
239
+ feedback, frag_correct, opt_del,
240
+ case_sense, time_align, left_to_right, wwl,
241
+ lm_file);
242
+ else if (strcmp(reffmt,"stm")== 0 && strcmp(hypfmt[nh],"txt") ==0){
243
+ #if DIFF_ENABLED
244
+ if (left_to_right)
245
+ scor[nh] =align_text_to_stm(refname, hypname[nh],title[nh],
246
+ 1,case_sense,feedback,id_type);
247
+ else {
248
+ fprintf(scfp,"Error: can't perform diff alignments on "
249
+ "right-to-left data\n");
250
+ exit(1);
251
+ }
252
+ #else
253
+ do_exit("Alignments via diff have been disabled",prog,1);
254
+ #endif
255
+ } else{
256
+ fprintf(stderr,"Error: Unable to score '%s' against '%s'\n",
257
+ hypfmt[nh],reffmt);
258
+ exit(1);
259
+ }
260
+
261
+ if (scor[nh] == (SCORES *)0){
262
+ fprintf(stderr,"%s: Alignment failed. Exiting.\n",prog);
263
+ exit(1);
264
+ }
265
+ } else { /* input came from piped input */
266
+ /* Set up the output root name */
267
+ if ((hroot = strrchr(scor[nsc]->title,'/')) != NULL){
268
+ strncpy((char *)hdir,scor[nsc]->title,hroot-scor[nsc]->title);
269
+ hdir[hroot-scor[nsc]->title] = '\0';
270
+ hroot++;
271
+ } else {
272
+ hroot = scor[nsc]->title;
273
+ strcpy((char *)hdir,".");
274
+ }
275
+ if ((out_dir != (char *)0) ||
276
+ strcmp(((out_dir != (char *)0) ? out_dir : (char *)hdir),".") != 0)
277
+ sprintf((char *)outroot,"%s/%s",((out_dir != (char *)0) ? out_dir : (char *)hdir),
278
+ (out_name != (char *)0) ? out_name : hroot);
279
+ else
280
+ sprintf((char *)outroot,"%s",(out_name != (char *)0) ? out_name : hroot);
281
+ }
282
+
283
+ if (BF_isSET(outputs,OUT_SUM))
284
+ print_system_summary(scor[nsc],
285
+ BF_isSET(outputs,OUT_STDOUT) ? "-": (char *)outroot,
286
+ 0, 0, 0, feedback);
287
+ if (BF_isSET(outputs,OUT_WWS)){
288
+ if (scor[nsc]->weight_ali)
289
+ print_system_summary(scor[nsc],
290
+ BF_isSET(outputs,OUT_STDOUT) ? "-": (char *)outroot,
291
+ 0, 0, 1, feedback);
292
+ else
293
+ printf(" Skipping WWS Report, no word weights supplied.\n");
294
+ }
295
+ if (BF_isSET(outputs,OUT_RSUM))
296
+ print_system_summary(scor[nsc],
297
+ BF_isSET(outputs,OUT_STDOUT) ? "-":(char *)outroot,
298
+ 0, 1, 0, feedback);
299
+ if (BF_isSET(outputs,OUT_SENT))
300
+ score_dtl_sent(scor[nsc], BF_isSET(outputs,OUT_STDOUT)?"-":(char *)outroot,
301
+ feedback);
302
+ if (BF_isSET(outputs,OUT_SPKR))
303
+ score_dtl_spkr(scor[nsc], BF_isSET(outputs,OUT_STDOUT)?"-":(char *)outroot,
304
+ feedback);
305
+ if (BF_isSET(outputs,OUT_DTL))
306
+ score_dtl_overall(scor[nsc],
307
+ BF_isSET(outputs,OUT_STDOUT) ? "-":(char *)outroot,
308
+ feedback);
309
+ if (BF_isSET(outputs,OUT_LUR))
310
+ print_lur(scor[nsc],
311
+ BF_isSET(outputs,OUT_STDOUT) ? "-":(char *)outroot, feedback);
312
+ if (BF_isSET(outputs,OUT_PRALIGN)){
313
+ FILE *fp = stdout;
314
+ if (BF_notSET(outputs,OUT_STDOUT))
315
+ fp = fopen(rsprintf("%s.pra",outroot),"w");
316
+ if (fp == (FILE *)0) fp = stdout;
317
+ if (feedback >= 1)
318
+ printf(" Writing string alignments to '%s'\n",
319
+ (fp == stdout) ? "stdout" :
320
+ rsprintf("%s.pra",outroot));
321
+ dump_SCORES_alignments(scor[nsc],fp,linewidth,0);
322
+ if (fp != stdout) fclose(fp);
323
+ }
324
+ if (BF_isSET(outputs,OUT_PRALIGN_FULL)){
325
+ FILE *fp = stdout;
326
+ if (BF_notSET(outputs,OUT_STDOUT))
327
+ fp = fopen(rsprintf("%s.prf",outroot),"w");
328
+ if (fp == (FILE *)0) fp = stdout;
329
+ if (feedback >= 1)
330
+ printf(" Writing string alignments to '%s'\n",
331
+ (fp == stdout) ? "stdout" :
332
+ rsprintf("%s.prf",outroot));
333
+ dump_SCORES_alignments(scor[nsc],fp,linewidth,1);
334
+ if (fp != stdout) fclose(fp);
335
+ }
336
+ if (BF_isSET(outputs,OUT_SGML)){
337
+ FILE *fp = stdout;
338
+ if (BF_notSET(outputs,OUT_STDOUT))
339
+ fp = fopen(rsprintf("%s.sgml",outroot),"w");
340
+ if (fp == (FILE *)0) fp = stdout;
341
+ if (fp != stdout && feedback >= 1)
342
+ printf(" Writing SGML string alignments to '%s'\n",
343
+ rsprintf("%s.sgml",outroot));
344
+ dump_SCORES_sgml(scor[nsc],fp,(TEXT *)":",(TEXT *)",");
345
+ if (fp != stdout) fclose(fp);
346
+ }
347
+ if (BF_isSET(outputs,OUT_NL_SGML)){
348
+ FILE *fp = stdout;
349
+ if (BF_notSET(outputs,OUT_STDOUT))
350
+ fp = fopen(rsprintf("%s.nl.sgml",outroot),"w");
351
+ if (fp == (FILE *)0) fp = stdout;
352
+ if (fp != stdout && feedback >= 1)
353
+ printf(" Writing Newline Separated SGML string alignments to '%s'\n",
354
+ rsprintf("%s.nl.sgml",outroot));
355
+ dump_SCORES_sgml(scor[nsc],fp,(TEXT *)"\n",(TEXT *)"\n");
356
+ if (fp != stdout) fclose(fp);
357
+ }
358
+ if (BF_isSET(conf_outputs,CONF_OUT_DET))
359
+ if (make_SCORES_DET_curve(&(scor[nsc]),1,(char *)outroot,feedback,"") != 0)
360
+ errors++;
361
+ if (BF_isSET(conf_outputs,CONF_OUT_BHIST))
362
+ if (make_binned_confidence(scor[nsc],(char *)outroot,feedback) != 0)
363
+ errors++;
364
+ if (BF_isSET(conf_outputs,CONF_OUT_HIST))
365
+ if (make_confidence_histogram(scor[nsc],(char *)outroot,feedback) != 0)
366
+ errors++;
367
+ if (BF_isSET(conf_outputs,CONF_OUT_SBHIST))
368
+ if (make_scaled_binned_confidence(scor[nsc],(char *)outroot,20,feedback) != 0)
369
+ errors++;
370
+
371
+ }
372
+
373
+ if (pipeout)
374
+ for (nsc=0; nsc < num_hyps + num_piped; nsc++)
375
+ dump_SCORES_sgml(scor[nsc],stdout,(TEXT *)"\n",(TEXT *)"\n");
376
+
377
+ /* clean up the score structures */
378
+ for (nsc=0; nsc < num_hyps + num_piped; nsc++)
379
+ SCORES_free(scor[nsc]);
380
+ if (wwl != (WWL *)0) free_WWL(&wwl);
381
+
382
+ if (feedback >= 1) {
383
+ if (errors == 0)
384
+ printf("\nSuccessful Completion\n");
385
+ else
386
+ printf("\nUnsuccessful Completion\n");
387
+ }
388
+ return(0);
389
+ }
390
+
391
+ void proc_args(int argc, char **argv, char *prog, char **rname, char **rfmt, char **hname, char **hfmt, int *nhyps, enum id_types *id_type, int *case_sense, int *outputs, char **title, int *feedback, int *linewidth, int *use_diff, char **out_dir, char **out_name, int *char_align, int *pipeout, int *pipein, int *infered_wordseg, char **lexicon, int *frag_correct, int *opt_del, int *inf_flags, int *stm2ctm_reduce, int *time_align, int *conf_outputs, int *left_to_right, char **wwl_file, char **lm_file){
392
+ int opt, fbset=0, outset=0, i, nh;
393
+ char *id;
394
+ struct stat fileinfo;
395
+
396
+ if (argc <= 1)
397
+ do_exit("Arguments reguired",prog,1);
398
+
399
+ *linewidth=1000;
400
+ *feedback=1;
401
+ *nhyps = 0;
402
+ *rname=(char *)0; *hname=(char *)0;
403
+ *rfmt=(char *)0; *hfmt=(char *)0;
404
+ id=(char *)0;
405
+ *outputs=0;
406
+ *case_sense=0;
407
+ *title=(char *)0;
408
+ *out_dir = (char *)0;
409
+ *out_name = (char *)0;
410
+ *use_diff = 0;
411
+ *char_align = 0;
412
+ *pipeout = 0;
413
+ *pipein = 0;
414
+ *infered_wordseg = 0;
415
+ *lexicon = (char *)0;
416
+ *frag_correct = 0;
417
+ *opt_del = 0;
418
+ *inf_flags = 0;
419
+ *stm2ctm_reduce = 0;
420
+ *time_align = 0;
421
+ *conf_outputs = CONF_OUT_NONE;
422
+ *left_to_right = 1;
423
+ *wwl_file = (char *)0;
424
+ *lm_file = (char *)0;
425
+
426
+ for (opt = 1; opt < argc && (*(argv[opt]) == '-'); opt++){
427
+ /* printf("Current OP %s\n",argv[opt]); */
428
+ if (strcmp(argv[opt],"-r") == 0){
429
+ if (argc < opt + 2) do_exit("Not enough Ref arguments",prog,1);
430
+ if (*(argv[opt+1]) == '-') do_exit("Req'd Ref File name",prog,1);
431
+ *rname = argv[++opt];
432
+ if (argc >= opt + 2 && *(argv[opt+1]) != '-') *rfmt = argv[++opt];
433
+ } else if (strcmp(argv[opt],"-h") == 0){
434
+ if (argc < opt + 2) do_exit("Not enough Hyp arguments",prog,1);
435
+ if (*(argv[opt+1]) == '-') do_exit("Req'd Hyp File name",prog,1);
436
+ hname[*nhyps] = argv[++opt];
437
+ if (argc >= opt + 2 && *(argv[opt+1]) != '-')
438
+ hfmt[*nhyps] = argv[++opt];
439
+ else
440
+ hfmt[*nhyps] = "trn";
441
+ if (argc >= opt + 2 && *(argv[opt+1]) != '-')
442
+ title[*nhyps] = argv[++opt];
443
+ else
444
+ title[*nhyps] = hname[*nhyps];
445
+ (*nhyps)++;
446
+ } else if (strcmp(argv[opt],"-i") == 0){
447
+ if (argc <= opt+1) do_exit("Not enough ID arguments",prog,1);
448
+ id = argv[++opt];
449
+ } else if (strcmp(argv[opt],"-l") == 0){
450
+ if (argc <= opt+1)
451
+ do_exit("Not enough Line Width arguments",prog,1);
452
+ *linewidth = atoi(argv[++opt]);
453
+ } else if (strcmp(argv[opt],"-L") == 0){
454
+ #ifdef WITH_SLM
455
+ if (argc <= opt+1)
456
+ do_exit("Not enough Language Model arguments",prog,1);
457
+ *lm_file = argv[++opt];
458
+ #else
459
+ do_exit("-L option used, but SLM toolkit not compiled into sctk\n",prog,1);
460
+ #endif
461
+ } else if (strcmp(argv[opt],"-f") == 0){
462
+ if (argc <= opt+1) do_exit("Not enough Feedback arguments",prog,1);
463
+ *feedback = atoi(argv[++opt]);
464
+ fbset = 1;
465
+ } else if (strcmp(argv[opt],"-o") == 0){
466
+ opt ++;
467
+ if (argc < opt + 1) do_exit("Not enough Report arguments",prog,1);
468
+ while (opt < argc && *(argv[opt]) != '-'){
469
+ if (strcmp(argv[opt],"sum") == 0)
470
+ BF_FLIP(*outputs,OUT_SUM);
471
+ else if (strcmp(argv[opt],"wws") == 0)
472
+ BF_FLIP(*outputs,OUT_WWS);
473
+ else if (strcmp(argv[opt],"rsum") == 0)
474
+ BF_FLIP(*outputs,OUT_RSUM);
475
+ else if ((strcmp(argv[opt],"pralign") == 0) ||
476
+ (strcmp(argv[opt],"pra") == 0))
477
+ BF_FLIP(*outputs,OUT_PRALIGN);
478
+ else if (strcmp(argv[opt],"prf") == 0)
479
+ BF_FLIP(*outputs,OUT_PRALIGN_FULL);
480
+ else if (strcmp(argv[opt],"lur") == 0)
481
+ BF_FLIP(*outputs,OUT_LUR);
482
+ else if (strcmp(argv[opt],"stdout") == 0)
483
+ BF_FLIP(*outputs,OUT_STDOUT);
484
+ else if (strcmp(argv[opt],"sgml") == 0)
485
+ BF_FLIP(*outputs,OUT_SGML);
486
+ else if (strcmp(argv[opt],"nl.sgml") == 0)
487
+ BF_FLIP(*outputs,OUT_NL_SGML);
488
+ else if (strcmp(argv[opt],"snt") == 0)
489
+ BF_FLIP(*outputs,OUT_SENT);
490
+ else if (strcmp(argv[opt],"spk") == 0)
491
+ BF_FLIP(*outputs,OUT_SPKR);
492
+ else if (strcmp(argv[opt],"dtl") == 0)
493
+ BF_FLIP(*outputs,OUT_DTL);
494
+ else if (strcmp(argv[opt],"all") == 0)
495
+ BF_FLIP(*outputs,OUT_PRALIGN + OUT_SUM + OUT_RSUM);
496
+ else if (strcmp(argv[opt],"none") == 0)
497
+ *outputs = 0;
498
+ else
499
+ fprintf(stderr,"Unknown report '%s'\n",argv[opt]);
500
+ opt++;
501
+ }
502
+ /* backup if we've gone to far */
503
+ if (opt < argc && *(argv[opt]) == '-') opt--;
504
+ outset=1;
505
+ } else if (strcmp(argv[opt],"-C") == 0){
506
+ opt ++;
507
+ if (argc < opt + 1)
508
+ do_exit("Not enough Confidence Report arguments",prog,1);
509
+ while (opt < argc && *(argv[opt]) != '-'){
510
+ if (strcmp(argv[opt],"det") == 0)
511
+ BF_FLIP(*conf_outputs,CONF_OUT_DET);
512
+ else if (strcmp(argv[opt],"bhist") == 0)
513
+ BF_FLIP(*conf_outputs,CONF_OUT_BHIST);
514
+ else if (strcmp(argv[opt],"sbhist") == 0)
515
+ BF_FLIP(*conf_outputs,CONF_OUT_SBHIST);
516
+ else if (strcmp(argv[opt],"hist") == 0)
517
+ BF_FLIP(*conf_outputs,CONF_OUT_HIST);
518
+ else if (strcmp(argv[opt],"none") == 0)
519
+ *conf_outputs = CONF_OUT_NONE;
520
+ else
521
+ fprintf(stderr,"Unknown confidence report '%s'\n",
522
+ argv[opt]);
523
+ opt++;
524
+ }
525
+ /* backup if we've gone to far */
526
+ if (opt < argc && *(argv[opt]) == '-') opt--;
527
+ outset=1;
528
+ } else if (strcmp(argv[opt],"-O") == 0){
529
+ if (argc <= opt+1)do_exit("Output directory not specified",prog,1);
530
+ *out_dir = argv[++opt];
531
+ } else if (strcmp(argv[opt],"-n") == 0){
532
+ if (argc <= opt+1)do_exit("Output name not specified",prog,1);
533
+ *out_name = argv[++opt];
534
+ } else if (strcmp(argv[opt],"-d") == 0){
535
+ #if DIFF_ENABLED
536
+ *use_diff = 1;
537
+ #else
538
+ do_exit("Alignments via diff have been disabled",prog,1);
539
+ #endif
540
+ } else if (strcmp(argv[opt],"-s") == 0){
541
+ *case_sense = 1;
542
+ } else if (strcmp(argv[opt],"-m") == 0){
543
+ *stm2ctm_reduce = REDUCE_NOTHING;
544
+ while (opt+1 < argc && *(argv[opt+1]) != '-') {
545
+ opt++;
546
+ if (strcmp(argv[opt],"ref") == 0)
547
+ BF_SET(*stm2ctm_reduce,REDUCE_REF_SEGMENTS);
548
+ else if (strcmp(argv[opt],"hyp") == 0)
549
+ BF_SET(*stm2ctm_reduce,REDUCE_HYP_WORDS);
550
+ else
551
+ do_exit(rsprintf("Unrecognized -m option '%s'",
552
+ argv[opt]),prog,1);
553
+ }
554
+ if (*stm2ctm_reduce == REDUCE_NOTHING)
555
+ *stm2ctm_reduce = REDUCE_REF_SEGMENTS;
556
+ } else if (strcmp(argv[opt],"-F") == 0){
557
+ *frag_correct = 1;
558
+ } else if (strcmp(argv[opt],"-D") == 0){
559
+ *opt_del = 1;
560
+ } else if (strcmp(argv[opt],"-c") == 0){
561
+ *char_align = CALI_ON;
562
+ while (opt+1 < argc && *(argv[opt+1]) != '-') {
563
+ opt++;
564
+ if (strcmp(argv[opt],"NOASCII") == 0)
565
+ BF_SET(*char_align,CALI_NOASCII);
566
+ else if (strcmp(argv[opt],"DH") == 0)
567
+ BF_SET(*char_align,CALI_DELHYPHEN);
568
+ else
569
+ do_exit(rsprintf("Unrecognized character alignment "
570
+ "option '%s'",argv[opt]),prog,1);
571
+ }
572
+ } else if (strcmp(argv[opt],"-e") == 0){
573
+ if (opt+1 >= argc || (opt+1 < argc && *(argv[opt+1]) == '-'))
574
+ do_exit("Argument required for character encoding\n",prog,1);
575
+ opt++;
576
+ if (!TEXT_set_encoding(argv[opt]))
577
+ do_exit(rsprintf("Unrecognized character encoding "
578
+ "option '%s'",argv[opt]),prog,1);
579
+ // Parse the optional localization
580
+ if (opt+1 < argc && *(argv[opt+1]) != '-'){
581
+ if (!TEXT_set_lang_prof(argv[opt+1]))
582
+ do_exit(rsprintf("Optional case conversion localization failed /%s/\n",
583
+ argv[opt+1]),prog,1);
584
+ opt++;
585
+ }
586
+ } else if (strcmp(argv[opt],"-p") == 0){
587
+ *pipeout = 1;
588
+ outset = 1;
589
+ } else if (strcmp(argv[opt],"-P") == 0){
590
+ *pipein = 1;
591
+ } else if (strcmp(argv[opt],"-T") == 0){
592
+ *time_align = 1;
593
+ } else if (strcmp(argv[opt],"-S") == 0){
594
+ opt ++;
595
+ if (argc < opt + 2) do_exit("Not enough Inferred Segmentation "
596
+ "arguments",prog,1);
597
+ if (opt < argc && *(argv[opt]) != '-')
598
+ if (strcmp(argv[opt],"algo1") == 0)
599
+ *infered_wordseg ^= INF_SEG_ALGO1;
600
+ else if (strcmp(argv[opt],"algo2") == 0)
601
+ *infered_wordseg ^= INF_SEG_ALGO2;
602
+ else
603
+ do_exit(rsprintf("Unrecognize inferred segmentation "
604
+ "algorithm '%s'",argv[opt]),prog,1);
605
+ else
606
+ do_exit("No Inferred Segmentation algorithm",prog,1);
607
+ opt++;
608
+ if (opt < argc && *(argv[opt]) != '-'){
609
+ if (stat(argv[opt],&fileinfo) != 0)
610
+ do_exit(rsprintf("Inferred Segmentation lexicon '%s'"
611
+ " does not exist",argv[opt]),prog,1);
612
+ *lexicon = argv[opt];
613
+ } else
614
+ do_exit("No Inferred Segmentation lexicon",prog,1);
615
+ if (opt+1 < argc && *(argv[opt+1]) != '-'){
616
+ opt++;
617
+ if (strcmp(argv[opt],"ASCIITOO") == 0)
618
+ BF_SET(*inf_flags,INF_ASCII_TOO);
619
+ else
620
+ do_exit(rsprintf("Unrecognized Inferred Segmentation"
621
+ " flag '%s'",argv[opt]),prog,1);
622
+ }
623
+ } else if (strcmp(argv[opt],"-w") == 0){
624
+ if (argc <= opt+1)do_exit("Word Weight list file not specified",prog,1);
625
+ *wwl_file = argv[++opt];
626
+ } else {
627
+ (void) fprintf(stderr,usage,prog);
628
+ printf("Illegal argument: %s\n",argv[opt]);
629
+ exit(1);
630
+ }
631
+ }
632
+
633
+ if (*pipeout){
634
+ *feedback = 0;
635
+ if (BF_isSET(*outputs,OUT_STDOUT))
636
+ do_exit("Error: output can not be both to stdout and a pipe",
637
+ prog,1);
638
+ }
639
+
640
+ /* set the default outputs */
641
+ if (*outputs == 0 && !outset)
642
+ BF_SET(*outputs,OUT_SUM + OUT_STDOUT);
643
+
644
+ /* reset feedback to 0 if STDOUT is used */
645
+ if ((BF_isSET(*outputs,OUT_STDOUT) && outset) &&
646
+ (*feedback > 0 && !fbset)){
647
+ /* fprintf(stderr,"Feedback level changed to 0\n");*/
648
+ *feedback = 0;
649
+ }
650
+
651
+ /* Check the input arguments */
652
+ if (! *pipein && ! (*rname != (char *)0 && *nhyps > 0))
653
+ do_exit("Input not specified, use transcription input or "
654
+ "piped input",prog,1);
655
+
656
+ if (*rname == (char *)0 && *nhyps > 0)
657
+ do_exit("Hypothesis input(s) specified, but no reference file",
658
+ prog,1);
659
+ if (*rname != (char *)0 && *nhyps == 0)
660
+ do_exit("Reference input specified, but no Hypothesis input(s).",
661
+ prog,1);
662
+
663
+ if (*rname != (char *)0 && *nhyps > 0){
664
+ if (stat(*rname,&fileinfo) != 0)
665
+ do_exit(rsprintf("Reference file '%s' does not exist",*rname),
666
+ prog,1);
667
+
668
+ for (nh=0; nh < *nhyps; nh++)
669
+ if (stat(hname[nh],&fileinfo) != 0)
670
+ do_exit(rsprintf("Hypothesis file '%s' does not exist",
671
+ hname[nh]),prog,1);
672
+
673
+ /* check the ref and hyp format arguments */
674
+ if (*rfmt == (char *)0) *rfmt = "trn";
675
+ if (! (strcmp(*rfmt,"trn") == 0 || strcmp(*rfmt,"ctm") == 0 ||
676
+ strcmp(*rfmt,"tmk") == 0 || strcmp(*rfmt,"stm") == 0))
677
+ do_exit(rsprintf("Reference file format '%s' not acceptable",*rfmt),
678
+ prog,1);
679
+
680
+ if (*hfmt == (char *)0) *hfmt = "trn";
681
+ for (i=0; i<*nhyps; i++)
682
+ if (! (strcmp(hfmt[i],"trn") == 0 || strcmp(hfmt[i],"ctm") == 0 ||
683
+ strcmp(hfmt[i],"tmk") == 0 || strcmp(hfmt[i],"txt") == 0))
684
+ do_exit(rsprintf("Hypothesis file format '%s' not acceptable",
685
+ hfmt[i]),prog,1);
686
+
687
+ /* check the id arguments */
688
+ if (id == (char *)0){
689
+ if (strcmp(*rfmt,"trn") == 0)
690
+ do_exit("Required utterance id (option -i) for"
691
+ " transcript mode", prog,1);
692
+ for (i=0; i<*nhyps; i++){
693
+ if (strcmp(hfmt[i],"trn") == 0)
694
+ do_exit("Required utterance id (option -i) for"
695
+ " transcript mode",prog,1);
696
+ }
697
+ }
698
+
699
+ /* only do time alignment on ctm to ctm */
700
+ if (*time_align){
701
+ if (strcmp(*rfmt,"ctm") != 0)
702
+ do_exit("Time-mediated alignments require the reference"
703
+ " file to be in CTM format",prog,1);
704
+ for (i=0; i<*nhyps; i++)
705
+ if (strcmp(hfmt[i],"ctm") != 0)
706
+ do_exit("Time-mediated alignments require the hypothesis"
707
+ " file to be in CTM format",prog,1);
708
+ }
709
+ }
710
+
711
+ if (id != (char *)0){
712
+ if (strcmp(id,"swb") == 0) *id_type=SWB;
713
+ else if (strcmp(id,"rm") == 0) *id_type=RM;
714
+ else if (strcmp(id,"wsj") == 0) *id_type=WSJ;
715
+ else if (strcmp(id,"spu_id") == 0) *id_type=SPUID;
716
+ else if (strcmp(id,"sp") == 0) *id_type=SP;
717
+ else
718
+ do_exit(rsprintf("Utterance id type '%s' not acceptable",id),
719
+ prog,1);
720
+ }
721
+
722
+ if (*stm2ctm_reduce){
723
+ if (strcmp(*rfmt,"stm") != 0)
724
+ do_exit("-m flag requires stm format reference file",prog,1);
725
+ for (i=0; i<*nhyps; i++)
726
+ if (strcmp(hfmt[i],"ctm") != 0)
727
+ do_exit("-m flag requires ctm format hypothesis file",prog,1);
728
+ if (*use_diff)
729
+ do_exit("-m flag can not be used with -d flag",prog,1);
730
+ }
731
+
732
+ if (*char_align && (*use_diff ||
733
+ (strcmp(*rfmt,"stm") == 0 && strcmp(*hfmt,"txt")==0)))
734
+ do_exit("Unable to do character alignments using diff\n",prog,1);
735
+
736
+ if (*wwl_file != (char *)0 && *lm_file != (char *)0)
737
+ do_exit("Flags '-L' and '-w' are mutually exclusive\n",prog,1);
738
+
739
+ if (*wwl_file != (char *)0){
740
+ if (*time_align) do_exit("Flags '-T' and '-w' are mutually exclusive\n",prog,1);
741
+ if (*char_align) do_exit("Flags '-c' and '-w' are mutually exclusive\n",prog,1);
742
+ if (*infered_wordseg) do_exit("Flags '-S' and '-w' are mutually exclusive\n",prog,1);
743
+ if (*use_diff) do_exit("Flags '-d' and '-w' are mutually exclusive\n",prog,1);
744
+ }
745
+ if (*lm_file != (char *)0){
746
+ if (*time_align) do_exit("Flags '-T' and '-L' are mutually exclusive\n",prog,1);
747
+ if (*char_align) do_exit("Flags '-c' and '-L' are mutually exclusive\n",prog,1);
748
+ if (*infered_wordseg) do_exit("Flags '-S' and '-L' are mutually exclusive\n",prog,1);
749
+ if (*use_diff) do_exit("Flags '-d' and '-L' are mutually exclusive\n",prog,1);
750
+ }
751
+
752
+ if (BF_isSET(*outputs,OUT_WWS))
753
+ if ((*wwl_file == (char *)0) && (*lm_file == (char *)0))
754
+ do_exit("-o wws option specified without a word weight file (via -w) or "
755
+ "LM file (via -L) specified\n",
756
+ prog,1) ;
757
+ }
758
+
759
+ void do_exit(char *desc, char *prog, int ret){
760
+ fprintf(stderr,usage,prog);
761
+ fprintf(stderr,"\n%s: Error, %s\n\n",prog,desc);
762
+ exit(ret);
763
+ }
764
+
SCTK/src/sclite/signtest.c ADDED
@@ -0,0 +1,304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**********************************************************************/
2
+ /* */
3
+ /* FILE: signtest.c */
4
+ /* WRITTEN BY: Jonathan G. Fiscus */
5
+ /* DATE: April 14 1989 */
6
+ /* NATIONAL INSTITUTE OF STANDARDS AND TECHNOLOGY */
7
+ /* SPEECH RECOGNITION GROUP */
8
+ /* */
9
+ /* USAGE: This uses the rank structure to perform */
10
+ /* the non-parametric Sign Test and generates */
11
+ /* a report. */
12
+ /* */
13
+ /* SOURCE:Statistics: Basic Techniques for Solving */
14
+ /* Applied Problems, by Stephen A. Book, 1977 */
15
+ /* */
16
+ /* See Also: The documentation file "signtest.doc" */
17
+ /* */
18
+ /**********************************************************************/
19
+
20
+ #include "sctk.h"
21
+
22
+ /****************************************************************/
23
+ /* main procedure to perform the sign test on the RANK */
24
+ /* structure. */
25
+ /****************************************************************/
26
+ void perform_signtest(RANK *rank, int verbose, int report, char *formula_str, char formula_id, int ***out_winner, char *outroot, int feedback, double ***out_confidence)
27
+ {
28
+ int comp1, comp2, **winner;
29
+ double **confidence;
30
+ FILE *fp = stdout;
31
+
32
+ if (report || verbose){
33
+ char *f = rsprintf("%s.sign",outroot);
34
+ if ((fp=(strcmp(outroot,"-") == 0) ? stdout : fopen(f,"w")) ==
35
+ (FILE *)0){
36
+ fprintf(stderr,"Warning: Open of %s for write failed. "
37
+ "Using stdout instead.\n",f);
38
+ fp = stdout;
39
+ } else
40
+ if (feedback >= 1) printf(" Output written to '%s'\n",f);
41
+ }
42
+
43
+ alloc_2dimZ(winner,rank->n_trt,rank->n_trt,int,NO_DIFF);
44
+ alloc_2dimZ(confidence,rank->n_trt,rank->n_trt,double,0.0);
45
+ *out_confidence = confidence;
46
+ *out_winner = winner;
47
+
48
+ for (comp1=0; comp1 < rank->n_trt -1; comp1++)
49
+ for (comp2=comp1+1; comp2< rank->n_trt ; comp2++){
50
+ winner[comp1][comp2] =
51
+ compute_signtest_for_treatment(rank,comp1,comp2,"Spkr",
52
+ formula_str,verbose,
53
+ formula_id=='E',fp,
54
+ &(confidence[comp1][comp2]));
55
+ }
56
+
57
+ if (report) print_trt_comp_matrix_for_RANK_one_winner(winner,rank,
58
+ "Comparison Matrix for the Sign Test",formula_str,
59
+ "Speaker",fp);
60
+ if (fp != stdout) fclose(fp);
61
+ }
62
+
63
+ /****************************************************************/
64
+ /* Given the two indexes of treatments to compare (in the */
65
+ /* RANK Struct) compute the Rank Sum statistics */
66
+ /* vars: */
67
+ /* zero_is_best : This identifies the "ideal" value for */
68
+ /* the value computed in the rank struct */
69
+ /* percentages. */
70
+ /****************************************************************/
71
+ int compute_signtest_for_treatment(RANK *rank, int treat1, int treat2, char *block_id, char *formula_str, int verbose, int zero_is_best, FILE *fp, double *confidence)
72
+ {
73
+ int sum_plus=0, sum_minus=0, sum_equal=0, i;
74
+ int block, max_len_block=0, max_len_treat=6;
75
+ int tptr[2]; /* a sorting pointer array for the treatment numbers */
76
+ char *pct_format, thresh_str[140];
77
+ TEXT *title_line = (TEXT *)0;
78
+ char *diff_line;
79
+ int paper_width = 79, rep_width, diff_col_len;
80
+ double equal_thresh = 0.005;
81
+ double sum_trt1=0.0, sum_trt2=0.0;
82
+
83
+ /* compute the maximum block title length */
84
+ max_len_block = strlen(block_id);
85
+ for (block=0; block <rank->n_blk ; block++)
86
+ if (strlen(rank->blk_name [ block ] ) > max_len_block)
87
+ max_len_block = strlen(rank->blk_name [ block ] );
88
+
89
+ if (max_len_treat < strlen(rank->trt_name [ treat1 ] ))
90
+ max_len_treat = strlen(rank->trt_name [ treat1 ] );
91
+
92
+ if (max_len_treat < strlen(rank->trt_name [ treat2 ] ))
93
+ max_len_treat = strlen(rank->trt_name [ treat2 ] );
94
+
95
+ /* set the treatment sorting array */
96
+ for (block=0; block <rank->n_blk ; block++){
97
+ sum_trt1 += rank->pcts [ block ][ treat1 ] ;
98
+ sum_trt2 += rank->pcts [ block ][ treat2 ] ;
99
+ }
100
+ if (sum_trt1 > sum_trt2)
101
+ tptr[0] = treat1, tptr[1] = treat2;
102
+ else
103
+ tptr[0] = treat2, tptr[1] = treat1;
104
+
105
+ /* set up format strings and titles */
106
+ sprintf(thresh_str,"(Threshold for equal percentages +- %5.3f)",
107
+ equal_thresh);
108
+ alloc_singarr(pct_format, max_len_treat + 2,char);
109
+ alloc_singarr(diff_line, max_len_treat*2 + 7,char);
110
+ pct_format[0] = '\0';
111
+ strcat(pct_format,center("",(max_len_treat-6)/2));
112
+ strcat(pct_format,"%6.2f");
113
+ strcat(pct_format,center("",max_len_treat - ((max_len_treat-6)/2 + 6) ));
114
+ sprintf(diff_line,"[%s - %s]",rank->trt_name[tptr[0]],
115
+ rank->trt_name[tptr[1]]);
116
+ diff_col_len = 15;
117
+ if (strlen(diff_line) > diff_col_len) diff_col_len=strlen(diff_line);
118
+
119
+ rep_width = max_len_block + max_len_treat * 2 + 4 * 3 + diff_col_len;
120
+
121
+ /* Print a detailed table showing sign differences */
122
+ if (verbose) {
123
+ sum_trt1 = sum_trt2 = 0.0;
124
+ fprintf(fp,"%s\n",center("Sign Test Calculations Table Comparing",
125
+ paper_width));
126
+ title_line = TEXT_strdup((TEXT *)rsprintf("%s %s Percentages for Systems %s and %s",
127
+ block_id, formula_str,rank->trt_name[tptr[0]],
128
+ rank->trt_name [ tptr[1] ] ));
129
+ fprintf(fp,"%s\n",center((char *)title_line,paper_width));
130
+ fprintf(fp,"%s\n\n",center(thresh_str,paper_width));
131
+
132
+ fprintf(fp,"%s",center("",(paper_width - rep_width)/2));
133
+ fprintf(fp,"%s",center("",max_len_block));
134
+ fprintf(fp," "); fprintf(fp,"%s",center("",max_len_treat));
135
+ fprintf(fp," "); fprintf(fp,"%s",center("",max_len_treat));
136
+ fprintf(fp," ");
137
+ fprintf(fp,"%s\n",center("Difference Sign",diff_col_len));
138
+
139
+ fprintf(fp,"%s",center("",(paper_width - rep_width)/2));
140
+ fprintf(fp,"%s",center(block_id,max_len_block));
141
+ fprintf(fp," ");
142
+ fprintf(fp,"%s",center(rank->trt_name [ tptr[0] ] ,max_len_treat));
143
+ fprintf(fp," ");
144
+ fprintf(fp,"%s",center(rank->trt_name [ tptr[1] ] ,max_len_treat));
145
+ fprintf(fp," ");
146
+ fprintf(fp,"%s\n",center(diff_line,diff_col_len));
147
+ fprintf(fp,"%s",center("",(paper_width - rep_width)/2));
148
+ for (i=0; i<rep_width; i++)
149
+ fprintf(fp,"-");
150
+ fprintf(fp,"\n");
151
+ }
152
+ for (block=0; block <rank->n_blk ; block++){
153
+ if (verbose) {
154
+ fprintf(fp,"%s",center("",(paper_width - rep_width)/2));
155
+ fprintf(fp,"%s",center(rank->blk_name [ block ] ,max_len_block));
156
+ fprintf(fp," ");
157
+ fprintf(fp,pct_format,rank->pcts [ block ][ tptr[0] ] );
158
+ fprintf(fp," ");
159
+ fprintf(fp,pct_format,rank->pcts [ block ][ tptr[1] ] );
160
+ fprintf(fp," ");
161
+ }
162
+ if (fabs(rank->pcts [ block ][ tptr[0] ] - rank->pcts [ block ][ tptr[1] ] ) <=
163
+ equal_thresh){
164
+ if (verbose) fprintf(fp,"%s\n",center("0",diff_col_len));
165
+ sum_equal++;
166
+ }
167
+ else if (rank->pcts [ block ][ tptr[0] ] < rank->pcts [ block ][ tptr[1] ] ){
168
+ if (verbose) fprintf(fp,"%s\n",center("-",diff_col_len));
169
+ sum_minus++;
170
+ }
171
+ else {
172
+ if (verbose) fprintf(fp,"%s\n",center("+",diff_col_len));
173
+ sum_plus++;
174
+ }
175
+ sum_trt1 += rank->pcts [ block ][ tptr[0] ] ;
176
+ sum_trt2 += rank->pcts [ block ][ tptr[1] ] ;
177
+ }
178
+ if (verbose){
179
+ fprintf(fp,"%s",center("",(paper_width - rep_width)/2));
180
+ for (i=0; i<rep_width; i++)
181
+ fprintf(fp,"-");
182
+ fprintf(fp,"\n");
183
+ /* an Average line */
184
+ fprintf(fp,"%s",center("",(paper_width - rep_width)/2));
185
+ fprintf(fp,"%s",center("Avg.",max_len_block));
186
+ fprintf(fp," ");
187
+ fprintf(fp,pct_format,sum_trt1 /rank->n_blk );
188
+ fprintf(fp," ");
189
+ fprintf(fp,pct_format,sum_trt2 /rank->n_blk );
190
+ fprintf(fp,"\n\n");
191
+
192
+ sprintf((char *)title_line,"No. Speakers with Positive %s Differences = N(+) = %2d",formula_str,sum_plus);
193
+ fprintf(fp,"%s\n",center((char *)title_line,paper_width));
194
+ sprintf((char *)title_line,"No. Speakers with Negative %s Differences = N(-) = %2d",formula_str,sum_minus);
195
+ fprintf(fp,"%s\n",center((char *)title_line,paper_width));
196
+ sprintf((char *)title_line,"No. Speakers with No %s Differences = N(0) = %2d",formula_str,sum_equal);
197
+ fprintf(fp,"%s\n",center((char *)title_line,paper_width));
198
+ fprintf(fp,"\n\n");
199
+ }
200
+
201
+ free_singarr(pct_format,char);
202
+ free_singarr(diff_line,char);
203
+ if (title_line != (TEXT *)0)
204
+ free_singarr(title_line, TEXT);
205
+ /* Analyze the Results */
206
+ { int result;
207
+ result = sign_test_analysis(sum_plus,sum_minus,sum_equal,"+","-",0,
208
+ 0.05,verbose, rank->trt_name [ tptr[0] ] ,
209
+ rank->trt_name [ tptr[1] ] ,
210
+ tptr,zero_is_best,fp,confidence);
211
+ /* if the result is significant, system which is better depends on if */
212
+ /* the treatments have been swapped, a negative result means tprt[0] is */
213
+ /* better, positive one tprt[1] is better */
214
+ return(result * ((tptr[0] == treat1) ? 1 : (-1)));
215
+ }
216
+ }
217
+
218
+ /****************************************************************/
219
+ /* Given the vital numbers for computing a rank sum test, */
220
+ /* Compute it, and if requested, print a verbose analysis */
221
+ /****************************************************************/
222
+ int sign_test_analysis(int num_a, int num_b, int num_z, char *str_a, char *str_b, int str_z, double alpha, int verbose, char *treat1_str, char *treat2_str, int *tptr, int zero_is_best, FILE *fp, double *confidence)
223
+ {
224
+ double test_stat, p=0.5;
225
+ int i;
226
+
227
+ num_b += (num_z / 2) + (num_z % 2);
228
+ num_a += (num_z / 2);
229
+ num_z = 0;
230
+
231
+ /* multiplication by 2 means it's a two-tailed test */
232
+ if (num_a != num_b)
233
+ test_stat = 2.0 * compute_acc_binomial(MIN(num_a,num_b),num_a+num_b,p);
234
+ else
235
+ test_stat = 1.0;
236
+ *confidence = test_stat;
237
+
238
+ if (verbose){
239
+ fprintf(fp,"The NULL Hypothesis:\n\n");
240
+ fprintf(fp," The number of speakers for which the differences is positive\n");
241
+ fprintf(fp," equals the number of speakers for which the differences is\n");
242
+ fprintf(fp," negative.\n");
243
+ fprintf(fp," P(N(+)) = P(N(-)) = 0.50\n\n");
244
+
245
+ fprintf(fp,"Alternate Hypothesis:\n\n");
246
+ fprintf(fp," The number of speakers for which the differences is positive \n");
247
+ fprintf(fp," is NOT equal to the number of speakers for which the difference\n");
248
+ fprintf(fp," is negative.\n\n");
249
+ fprintf(fp,"Decision Analysis:\n\n");
250
+ fprintf(fp," Assumptions:\n");
251
+ fprintf(fp," A1: The distibrution of positive and negative differences\n");
252
+ fprintf(fp," follows the binomial distribution for N fair coin tosses.\n");
253
+ fprintf(fp,"\n");
254
+ fprintf(fp," A2: In order to resolve the complication caused by cases where the\n");
255
+ fprintf(fp," difference in Word Accuracy is zero, half of the cases will\n");
256
+ fprintf(fp," be assigned to N(+) and half to N(-). In the event of an\n");
257
+ fprintf(fp," odd number of zero differences, N(-) will get one extra, this\n");
258
+ fprintf(fp," reduces the probability of there being a difference between\n");
259
+ fprintf(fp," the two systems.\n\n");
260
+ fprintf(fp," Rejection criterion:\n");
261
+ fprintf(fp," Reject the null hypothesis at the 95%% confidence level based\n");
262
+ fprintf(fp," on the following critical values table. N is the number of\n");
263
+ fprintf(fp," speakers being compared and N(-) is the number of negative\n");
264
+ fprintf(fp," differences.\n\n");
265
+ /* print a table of critical values */
266
+ fprintf(fp," MIN(N(-),N(+)) P(MIN(N(-),N(+)) | N=%2d)\n",num_a+num_b);
267
+
268
+ fprintf(fp," -------------- ------------------------\n");
269
+ for (i=0; i <= (num_a+num_b)/2 && (i - 3) <= num_b; i++){
270
+ double val = 2.0*compute_acc_binomial(i,num_a+num_b,p),
271
+ valp1 = 2.0*compute_acc_binomial(i+1,num_a+num_b,p);
272
+ if (val >= 0.0005)
273
+ fprintf(fp," %3d %5.3f", i,val);
274
+ else
275
+ fprintf(fp," %3d <0.001 ", i);
276
+
277
+ if ((val < alpha) && (valp1 > alpha))
278
+ fprintf(fp," <--- Null Hypothesis rejected at or below this point\n");
279
+ else
280
+ fprintf(fp,"\n");
281
+ }
282
+ fprintf(fp,"\n");
283
+ fprintf(fp," Decision:\n");
284
+
285
+ fprintf(fp," There were N(-)=%d negative differences , the probability of\n",num_b);
286
+ fprintf(fp," it occurring is %5.3f, therefore the null hypothesis ",test_stat);
287
+ if (test_stat < alpha){
288
+ fprintf(fp,"is REJECTED\n");
289
+ fprintf(fp," in favor of the Alternate Hypothesis. Further, %s is the\n",
290
+ (zero_is_best) ? treat2_str : treat1_str);
291
+ fprintf(fp," better System.\n");
292
+ } else{
293
+ fprintf(fp,"is ACCEPTED\n");
294
+ fprintf(fp," There is no statistical difference between %s and %s\n",treat1_str,treat2_str);
295
+ }
296
+ form_feed(fp);
297
+ }
298
+ if (test_stat < alpha){
299
+ if (0) fprintf(fp,"Returning Result %d\n",TEST_DIFF * ((zero_is_best) ? 1 : -1));
300
+ return(TEST_DIFF * ((zero_is_best) ? 1 : -1));
301
+ }
302
+ return(NO_DIFF);
303
+ }
304
+
SCTK/src/sclite/slm_intf.c ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "sctk.h"
2
+
3
+
4
+ /*
5
+ File: slm_intf.c
6
+ Date: March 20, 1998
7
+
8
+
9
+ This file contains interface functions to lookup probs from a language
10
+ model read in by the SLM toolkit libraries.
11
+
12
+ The only function that is always defined is lookup_lm_word_weight. If the
13
+ SLM is not included, then executing this function is an error.
14
+
15
+ */
16
+
17
+
18
+ void lookup_lm_word_weight(ARC *arc, void *ptr){
19
+
20
+ #ifdef WITH_SLM
21
+ WORD *tw = (WORD *)(arc->data);
22
+ static init = 1;
23
+ static ng_t ng;
24
+ static fb_info *fb_list;
25
+ WORD *w = (WORD *)arc->data, *w_m1, *w_m2;
26
+ double sum_weight, lu_prob, def_w;
27
+ int nprob;
28
+ ARC_LIST_ATOM *oarc_a, *oarc_b;
29
+ int dbg = 0;
30
+
31
+ if (init){
32
+ initialize_lm(&ng,&fb_list, (char *)ptr, dbg);
33
+ init = 0;
34
+ }
35
+
36
+ #define W_func(_d) (log(1.0 / (_d)) * 1.4426950408889634074)
37
+
38
+ /* Set the default weight for this word */
39
+ def_w = (w->opt_del) ? 0.0 : 20.0;
40
+
41
+ nprob = 0, sum_weight = 0;
42
+
43
+ if (dbg) printf("w->value= %s\n",w->value);
44
+ /* search for the previous word */
45
+ if (! arc->from_node->start_state && ng.n > 1 && ! w->opt_del){
46
+ for (oarc_a = arc->from_node->in_arcs; oarc_a != NULL; oarc_a=oarc_a->next){
47
+ w_m1 = (WORD*)(oarc_a->arc->data);
48
+
49
+ if (! oarc_a->arc->from_node->start_state && ng.n > 2){
50
+ for (oarc_b = oarc_a->arc->from_node->in_arcs; oarc_b != NULL; oarc_b=oarc_b->next){
51
+ w_m2 = (WORD*)(oarc_b->arc->data);
52
+ if (dbg) printf(" w-1= %s w-2= %s\n",w_m1->value,w_m2->value);
53
+ sum_weight +=
54
+ (tg_lookup(w, w_m1, w_m2, &ng, fb_list, &lu_prob, dbg)) ? W_func(lu_prob) : def_w;
55
+ nprob ++;
56
+ }
57
+ } else {
58
+ w_m2 = (WORD *)0;
59
+ if (dbg) printf(" w-1= %s w-2= No-context\n",w_m1->value);
60
+ sum_weight +=
61
+ (tg_lookup(w, w_m1, w_m2, &ng, fb_list, &lu_prob, dbg)) ? W_func(lu_prob) : def_w;
62
+ nprob ++;
63
+ }
64
+ }
65
+ } else {
66
+ w_m1 = w_m2 = (WORD *)0;
67
+ if (dbg) printf(" w-1= No-context w-2= No-context\n");
68
+ if (! w->opt_del)
69
+ sum_weight +=
70
+ (tg_lookup(w, w_m1, w_m2, &ng, fb_list, &lu_prob, dbg)) ? W_func(lu_prob) : def_w;
71
+ nprob ++;
72
+ }
73
+ if (dbg) printf(" AvgWeight= \t%g\n",sum_weight/nprob);
74
+ tw->weight = sum_weight / nprob;
75
+ #else
76
+ fprintf(scfp,"Error: a call to lookup_lm_word_weight() was made even though\n"
77
+ " the SLM toolkit has not been included in the compilation of SCTK\n");
78
+ exit(1);
79
+ #endif
80
+ }
81
+
82
+ #ifdef WITH_SLM
83
+
84
+ /*****************************************************************/
85
+ /* given upto three WORDS, lookup the N-gram in a language model */
86
+
87
+ int tg_lookup(WORD *w, WORD *w_m1, WORD *w_m2, ng_t *ng, fb_info *fb_list, double *prob, int dbg){
88
+ int32 h_lu, m1_lu, m2_lu;
89
+ id__t h_id, m_id[3];
90
+ int bo_case = 0, acl = 0;
91
+ int actual_context;
92
+
93
+ if (sih_lookup(ng->vocab_ht,
94
+ (char *)((w->opt_del)?w->intern_value:w->value),&h_lu) == 0){
95
+ if (dbg) printf(" Head Word Not in Vocab\n");
96
+ *prob = 0.0;
97
+ return(0);
98
+ }
99
+ h_id = (id__t)h_lu;
100
+
101
+ if (w_m1 != (WORD *)0){
102
+ sih_lookup(ng->vocab_ht,
103
+ (char *)((w_m1->opt_del)?w_m1->intern_value:w_m1->value),&m1_lu);
104
+ actual_context = 1;
105
+ m_id[0] = (id__t)m1_lu;
106
+
107
+ if (w_m2 != (WORD *)0){
108
+ sih_lookup(ng->vocab_ht,
109
+ (char *)((w_m2->opt_del)?w_m2->intern_value:w_m2->value),&m2_lu);
110
+ actual_context = 2;
111
+ m_id[0] = (id__t)m2_lu;
112
+ m_id[1] = (id__t)m1_lu;
113
+ }
114
+ } else {
115
+ actual_context = 0;
116
+ }
117
+
118
+ *prob = calc_prob_of(h_id,m_id,actual_context,ng,(arpa_lm_t *)0,
119
+ fb_list,&bo_case,&acl,0);
120
+
121
+ if (dbg){
122
+ printf(" Texts: P(%s | ",(char *)w->value);
123
+ if (ng->n > 2) printf("%s ",(w_m2 == (WORD *)0) ? "UNK" : (char *)w_m2->value);
124
+ if (ng->n > 1) printf("%s",(w_m1 == (WORD *)0) ? "UNK" : (char *)w_m1->value);
125
+ printf(") = %g bo_case ",*prob);
126
+ decode_bo_case(bo_case,acl,stdout);
127
+ }
128
+ return(1);
129
+ }
130
+
131
+ /*****************************************************************/
132
+ /* Read in a lanagauge model, an set up the structures. */
133
+
134
+ void initialize_lm(ng_t *ng, fb_info **fb_list, char *lm_file, int dbg){
135
+
136
+ if (lm_file != (char *)0){
137
+ if (dbg) printf("Loading LM file '%s'\n",lm_file);
138
+ load_lm(ng,lm_file); /* if it failes, it dies */
139
+ if (dbg) {
140
+ printf("LM read in -\n");
141
+ printf(" version: %d\n",ng->version);
142
+ printf(" #-gram order: %d\n",ng->n);
143
+ printf(" vocabulary size: %d\n",ng->vocab_size);
144
+ }
145
+ *fb_list = gen_fb_list(ng->vocab_ht,
146
+ ng->vocab_size,
147
+ ng->vocab,
148
+ ng->context_cue,
149
+ 0, 0, 0, 0,
150
+ "");
151
+
152
+ /* This code works as a test, except the printout for bo_case is wrong for
153
+ the trigram. it output 3x2x1 instead of 3x2-1 */
154
+
155
+ if (dbg){
156
+ int32 lu1, lu2, lu3; id__t h_id, m_id[4]; double prob;
157
+ int bo_case = 0, acl = 0;
158
+
159
+ if (sih_lookup(ng->vocab_ht,"the",&lu1) == 0)
160
+ printf(" Head Word Not in Vocab\n");
161
+ m_id[0] = lu1;
162
+ h_id = lu1;
163
+ prob = calc_prob_of(h_id,m_id,0,ng,(arpa_lm_t *)0,*fb_list,&bo_case,&acl,0);
164
+ printf(" P(%s| ) = %g bo_case ",ng->vocab[lu1],prob);
165
+ decode_bo_case(bo_case,acl,stdout);
166
+
167
+ if (ng->n > 1) {
168
+ if (sih_lookup(ng->vocab_ht,"dow",&lu2) == 0)
169
+ printf(" Head Word Not in Vocab\n");
170
+ m_id[0] = lu1;
171
+ h_id = lu2;
172
+ prob = calc_prob_of(h_id,m_id,1,ng,(arpa_lm_t *)0,*fb_list,&bo_case,&acl,0);
173
+ printf(" P(%s | the) = %g bo_case ",ng->vocab[lu2],prob);
174
+ decode_bo_case(bo_case,acl,stdout);
175
+
176
+ if (ng->n > 2) {
177
+ if (sih_lookup(ng->vocab_ht,"jones",&lu3) == 0)
178
+ printf(" Head Word Not in Vocab\n");
179
+ m_id[0] = lu1;
180
+ m_id[1] = lu2;
181
+ h_id = lu3;
182
+ prob = calc_prob_of(h_id,m_id,2,ng,(arpa_lm_t *)0,*fb_list,&bo_case,&acl,0);
183
+ printf(" P(jones | the dow) = %g bo_case ",prob);
184
+ decode_bo_case(bo_case,acl,stdout);
185
+ }
186
+ }
187
+ }
188
+
189
+
190
+ } else {
191
+ fprintf(stderr,"Error: no lm_file name passed to alignment\n");
192
+ }
193
+ }
194
+
195
+ #endif
SCTK/src/sclite/statdist.o ADDED
Binary file (24.8 kB). View file
 
SCTK/src/sclite/stm.h ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ typedef struct stm_seg_struct{
3
+ TEXT *file;
4
+ TEXT *chan;
5
+ TEXT *spkr;
6
+ double t1;
7
+ double t2;
8
+ int flag1;
9
+ TEXT *labels;
10
+ TEXT *text;
11
+ } STM_SEG;
12
+
13
+ typedef struct stm_struct{
14
+ int max;
15
+ int s;
16
+ int num;
17
+ STM_SEG *seg;
18
+ } STM;
19
+
20
+ STM *alloc_STM(int n);
21
+ void expand_STM(STM *stm);
22
+ void free_STM(STM *stm);
23
+ void fill_STM(FILE *fp, STM *stm, char *fname, boolean *end_of_file, int case_sense, int *perr);
24
+ void locate_STM_boundary(STM *stm, int start, int by_file, int by_chan, int *end);
25
+ void dump_STM_words(STM *stm,int s, int e, char *file);
26
+ void dump_STM(STM *stm, int s, int e);
27
+ void read_stm_line(TEXT **buf, int *len, FILE *fp);
28
+ void parse_stm_line(STM_SEG *seg, TEXT **buf_ptr, int *buf_len, int case_sense, int dbg);
29
+ void free_STM_SEG(STM_SEG *seg);
30
+ void convert_stm_to_word_list(char *file, char *words, int case_sense, int *num_ref);
31
+ void fill_STM_structure(STM *stm, FILE *fp_stm, char *stm_file, int *stm_file_end, int case_sense);