1
15
16 package gate.annotation;
17
18 import java.awt.*;
19 import java.beans.BeanInfo;
20 import java.beans.Introspector;
21 import java.text.NumberFormat;
22 import java.util.*;
23
24 import javax.swing.*;
25 import javax.swing.table.*;
26
27 import gate.*;
28 import gate.creole.*;
29 import gate.swing.XJTable;
30 import gate.util.*;
31
32
37 public class CorpusAnnotationDiff extends AbstractVisualResource
38 implements Scrollable{
39
40 protected int maxUnitIncrement = 10;
42
43
44 private static final boolean DEBUG = false;
45
46
48 private Document keyDocument = null;
49
50
52 private Corpus keyCorpus = null;
53
54
57 private String keyAnnotationSetName = null;
58
59
62 private Document responseDocument = null;
63
64
67 private Corpus responseCorpus = null;
68
69
72 private String responseAnnotationSetName = null;
73
74
77 private String responseAnnotationSetNameFalsePoz = null;
78
79
80 private AnnotationSchema annotationSchema = null;
81
82
85 private Set keyFeatureNamesSet = null;
86
87
88 private double precisionStrict = 0.0;
89
90 private double precisionLenient = 0.0;
91
92 private double precisionAverage = 0.0;
93
94
95 private double recallStrict = 0.0;
96
97 private double recallLenient = 0.0;
98
99 private double recallAverage = 0.0;
100
101
102 private double falsePositiveStrict = 0.0;
103
104 private double falsePositiveLenient = 0.0;
105
106 private double falsePositiveAverage = 0.0;
107
108
109 private double fMeasureStrict = 0.0;
110
111 private double fMeasureLenient = 0.0;
112
113 private double fMeasureAverage = 0.0;
114
115 public static double weight = 0.5;
116
117
120 private String annotationTypeForFalsePositive = null;
121
122
123 protected static NumberFormat formatter = NumberFormat.getInstance();
124
125
126 private XJTable diffTable = null;
127
128
129 private Set diffSet = null;
130
131
133 private Set keyPartiallySet = null;
134
135 private Set responsePartiallySet = null;
136
137
138 private java.util.List keyAnnotList = null;
139
140 private java.util.List responseAnnotList = null;
141
142
144 private boolean textMode = false;
145
146
149 public static final int MAX_TYPES = 5;
150
151 public static final int DEFAULT_TYPE = 0;
152
153 public static final int CORRECT_TYPE = 1;
154
156 public static final int PARTIALLY_CORRECT_TYPE = 2;
157
159 public static final int SPURIOUS_TYPE = 3;
160
162 public static final int MISSING_TYPE = 4;
163
164
165 private final Color RED = new Color(255,173,181);
166
167 private final Color GREEN = new Color(173,255,214);
168
169 private final Color WHITE = new Color(255,255,255);
170
171 private final Color BLUE = new Color(173,215,255);
172
173 private final Color YELLOW = new Color(255,231,173);
174
175
176 private final int NULL_TYPE = -1;
177
178 private final Color BLACK = new Color(0,0,0);
179
180 private Color colors[] = new Color[MAX_TYPES];
181
182
183 private JScrollPane scrollPane = null;
184
185
188 private int typeCounter[] = new int[MAX_TYPES];
189
190
191 public CorpusAnnotationDiff(){
192 }
194
199 public void setAnnotationTypeForFalsePositive(String anAnnotType){
200 annotationTypeForFalsePositive = anAnnotType;
201 }
203
207 public String getAnnotationTypeForFalsePositive(){
208 return annotationTypeForFalsePositive;
209 }
211
214 public void setKeyCorpus(Corpus aKeyCorpus) {
215 keyCorpus = aKeyCorpus;
216 }
218
219 public Corpus getKeyCorpus(){
220 return keyCorpus;
221 }
223
228 public void setKeyAnnotationSetName(String aKeyAnnotationSetName){
229 keyAnnotationSetName = aKeyAnnotationSetName;
230 }
232
236 public String getKeyAnnotationSetName(){
237 return keyAnnotationSetName;
238 }
240
244 public void setKeyFeatureNamesSet(Set aKeyFeatureNamesSet){
245 keyFeatureNamesSet = aKeyFeatureNamesSet;
246 }
248
252 public Set getKeyFeatureNamesSet(){
253 return keyFeatureNamesSet;
254 }
256
261 public void setResponseAnnotationSetName(String aResponseAnnotationSetName){
262 responseAnnotationSetName = aResponseAnnotationSetName;
263 }
265
269 public String getResponseAnnotationSetName(){
270 return responseAnnotationSetName;
271 }
273
278 public void setResponseAnnotationSetNameFalsePoz(
279 String aResponseAnnotationSetNameFalsePoz){
280 responseAnnotationSetNameFalsePoz = aResponseAnnotationSetNameFalsePoz;
281 }
283
288 public String getResponseAnnotationSetNameFalsePoz(){
289 return responseAnnotationSetNameFalsePoz;
290 }
292
295 public void setTextMode(Boolean aTextMode){
296 textMode = aTextMode.booleanValue();
299 }
301
302 public boolean isTextMode(){
303 return textMode;
304 }
306
307 public Set getAnnotationsOfType(int annotType){
308 HashSet results = new HashSet();
309 if (diffSet == null) return results;
310 Iterator diffIter = diffSet.iterator();
311 while(diffIter.hasNext()){
312 DiffSetElement diffElem = (DiffSetElement)diffIter.next();
313 switch(annotType){
314 case CORRECT_TYPE:{
315 if (diffElem.getRightType() == CORRECT_TYPE)
316 results.add(diffElem.getRightAnnotation());
317 }break;
318 case PARTIALLY_CORRECT_TYPE:{
319 if (diffElem.getRightType() == PARTIALLY_CORRECT_TYPE)
320 results.add(diffElem.getRightAnnotation());
321 }break;
322 case SPURIOUS_TYPE:{
323 if (diffElem.getRightType() == SPURIOUS_TYPE)
324 results.add(diffElem.getRightAnnotation());
325 }break;
326 case MISSING_TYPE:{
327 if (diffElem.getLeftType() == MISSING_TYPE)
328 results.add(diffElem.getLeftAnnotation());
329 }break;
330 case DEFAULT_TYPE:{
331 if (diffElem.getLeftType() == DEFAULT_TYPE)
332 results.add(diffElem.getLeftAnnotation());
333 }break;
334 } } return results;
337 }
339
345 public Object getParameterValue(String paramaterName)
346 throws ResourceInstantiationException{
347 return AbstractResource.getParameterValue(this, paramaterName);
348 }
349
350
356 public void setParameterValue(String paramaterName, Object parameterValue)
357 throws ResourceInstantiationException{
358 BeanInfo resBeanInf = null;
360 try {
361 resBeanInf = Introspector.getBeanInfo(this.getClass(), Object.class);
362 } catch(Exception e) {
363 throw new ResourceInstantiationException(
364 "Couldn't get bean info for resource " + this.getClass().getName()
365 + Strings.getNl() + "Introspector exception was: " + e
366 );
367 }
368 AbstractResource.setParameterValue(this, resBeanInf, paramaterName, parameterValue);
369 }
370
371
377 public void setParameterValues(FeatureMap parameters)
378 throws ResourceInstantiationException{
379 AbstractResource.setParameterValues(this, parameters);
380 }
381
382
383
384
388
389 public double getPrecisionStrict(){
390 return precisionStrict;
391 }
393
394 public double getPrecisionLenient(){
395 return precisionLenient;
396 }
398
399 public double getPrecisionAverage(){
400 return precisionAverage;
401 }
403
404 public double getFMeasureStrict(){
405 return fMeasureStrict;
406 }
408
409 public double getFMeasureLenient(){
410 return fMeasureLenient;
411 }
413
414 public double getFMeasureAverage(){
415 return fMeasureAverage;
416 }
418
422
423 public double getRecallStrict(){
424 return recallStrict;
425 }
427
428 public double getRecallLenient(){
429 return recallLenient;
430 }
432
433 public double getRecallAverage(){
434 return recallAverage;
435 }
437
441
442 public double getFalsePositiveStrict(){
443 return falsePositiveStrict;
444 }
446
447 public double getFalsePositiveLenient(){
448 return falsePositiveLenient;
449 }
451
452 public double getFalsePositiveAverage(){
453 return falsePositiveAverage;
454 }
456
461 public void setResponseCorpus(Corpus aResponseCorpus) {
462 responseCorpus = aResponseCorpus;
463 }
465
471 public void setAnnotationSchema(AnnotationSchema anAnnotationSchema) {
472 annotationSchema = anAnnotationSchema;
473 }
475
476 public AnnotationSchema getAnnotationSchema(){
477 return annotationSchema;
478 }
480 public Dimension getPreferredScrollableViewportSize() {
481 return getPreferredSize();
482 }
484 public int getScrollableUnitIncrement(Rectangle visibleRect,
485 int orientation, int direction) {
486 return maxUnitIncrement;
487 }
489 public int getScrollableBlockIncrement(Rectangle visibleRect,
490 int orientation, int direction) {
491 if (orientation == SwingConstants.HORIZONTAL)
492 return visibleRect.width - maxUnitIncrement;
493 else
494 return visibleRect.height - maxUnitIncrement;
495 }
497 public boolean getScrollableTracksViewportWidth() {
498 return false;
499 }
501 public boolean getScrollableTracksViewportHeight() {
502 return false;
503 }
504
505
509 public Resource init() throws ResourceInstantiationException {
510 colors[DEFAULT_TYPE] = WHITE;
511 colors[CORRECT_TYPE] = GREEN;
512 colors[SPURIOUS_TYPE] = RED;
513 colors[PARTIALLY_CORRECT_TYPE] = BLUE;
514 colors[MISSING_TYPE] = YELLOW;
515
516 keyPartiallySet = new HashSet();
518 responsePartiallySet = new HashSet();
519
520 AnnotationSet keyAnnotSet = null;
522 AnnotationSet responseAnnotSet = null;
523
524 if(annotationSchema == null)
525 throw new ResourceInstantiationException("No annotation schema defined !");
526
527 if(keyCorpus == null || 0 == keyCorpus.size())
528 throw new ResourceInstantiationException("No key corpus or empty defined !");
529
530 if(responseCorpus == null || 0 == responseCorpus.size())
531 throw new ResourceInstantiationException("No response corpus or empty defined !");
532
533 for (int type=0; type < MAX_TYPES; type++)
535 typeCounter[type] = 0;
536 diffSet = new HashSet();
537
538 for(int i=0; i<keyCorpus.size(); ++i) {
539 keyDocument = (Document) keyCorpus.get(i);
540
542 Document doc;
543 responseDocument = null;
544 for(int j=0; j<responseCorpus.size(); ++j) {
545 doc = (Document) responseCorpus.get(j);
546 if(0 == doc.getName().compareTo(keyDocument.getName())
547 || 0 == doc.getSourceUrl().getFile().compareTo(
548 keyDocument.getSourceUrl().getFile())) {
549 responseDocument = doc;
550 break; } }
554 if(null == responseDocument) {
555 Out.prln("There is no mach in responce corpus for document '"
556 +keyDocument.getName()+"' from key corpus");
557 continue; }
560 if (keyAnnotationSetName == null) {
561 keyAnnotSet = keyDocument.getAnnotations().get(
563 annotationSchema.getAnnotationName());
564 }
565 else {
566 keyAnnotSet = keyDocument.getAnnotations(keyAnnotationSetName).get(
567 annotationSchema.getAnnotationName());
568 }
570 if (keyAnnotSet == null)
571 keyAnnotList = new LinkedList();
574 else
575 keyAnnotList = new LinkedList(keyAnnotSet);
578
579 if (responseAnnotationSetName == null)
580 responseAnnotSet = responseDocument.getAnnotations().get(
582 annotationSchema.getAnnotationName());
583 else
584 responseAnnotSet = responseDocument.getAnnotations(responseAnnotationSetName).
585 get(annotationSchema.getAnnotationName());
586
587 if (responseAnnotSet == null)
588 responseAnnotList = new LinkedList();
591 else
592 responseAnnotList = new LinkedList(responseAnnotSet);
595
596 AnnotationSetComparator asComparator = new AnnotationSetComparator();
598 Collections.sort(keyAnnotList, asComparator);
599 Collections.sort(responseAnnotList, asComparator);
600
601 doDiff(keyAnnotList, responseAnnotList);
604 }
606 if (textMode) return this;
608
609 formatter.setMaximumIntegerDigits(1);
613 formatter.setMinimumFractionDigits(4);
614 formatter.setMinimumFractionDigits(4);
615
616 AnnotationDiffTableModel diffModel = new AnnotationDiffTableModel(diffSet);
618 diffTable = new XJTable(diffModel);
620 diffTable.setAlignmentX(Component.LEFT_ALIGNMENT);
621 AnnotationDiffCellRenderer cellRenderer = new AnnotationDiffCellRenderer();
623 diffTable.setDefaultRenderer(java.lang.String.class,cellRenderer);
624 diffTable.setDefaultRenderer(java.lang.Long.class,cellRenderer);
625
627 SwingUtilities.invokeLater(new Runnable(){
629 public void run(){
630 arangeAllComponents();
631 }
632 });
633
634 if (DEBUG)
635 printStructure(diffSet);
636
637 return this;
638 }
640
643 protected void arangeAllComponents(){
644 this.removeAll();
645 BoxLayout boxLayout = new BoxLayout(this,BoxLayout.Y_AXIS);
647 this.setLayout(boxLayout);
648
649 JTableHeader tableHeader = diffTable.getTableHeader();
650 tableHeader.setAlignmentX(Component.LEFT_ALIGNMENT);
651 this.add(tableHeader);
652 diffTable.setAlignmentX(Component.LEFT_ALIGNMENT);
653 this.add(diffTable);
655
656
657 JPanel infoBox = new JPanel();
661 infoBox.setLayout(new BoxLayout(infoBox,BoxLayout.X_AXIS));
662 infoBox.setAlignmentX(Component.LEFT_ALIGNMENT);
663
666 Box box = new Box(BoxLayout.Y_AXIS);
667 JLabel jLabel = new JLabel("LEGEND");
668 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
669 jLabel.setOpaque(true);
670 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
671 box.add(jLabel);
672
673 jLabel = new JLabel("Missing (present in Key but not in Response): " +
674 typeCounter[MISSING_TYPE]);
675 jLabel.setForeground(BLACK);
676 jLabel.setBackground(colors[MISSING_TYPE]);
677 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
678 jLabel.setOpaque(true);
679 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
680 box.add(jLabel);
681
682 box.add(Box.createRigidArea(new Dimension(0,5)));
684
685 jLabel = new JLabel("Correct (total match): " + typeCounter[CORRECT_TYPE]);
686 jLabel.setForeground(BLACK);
687 jLabel.setBackground(colors[CORRECT_TYPE]);
688 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
689 jLabel.setOpaque(true);
690 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
691 box.add(jLabel);
692
693 box.add(Box.createRigidArea(new Dimension(0,5)));
695
696 jLabel =new JLabel("Partially correct (overlap in Key and Response): "+
697 typeCounter[PARTIALLY_CORRECT_TYPE]);
698 jLabel.setForeground(BLACK);
699 jLabel.setBackground(colors[PARTIALLY_CORRECT_TYPE]);
700 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
701 jLabel.setOpaque(true);
702 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
703 box.add(jLabel);
704
705 box.add(Box.createRigidArea(new Dimension(0,5)));
707
708 jLabel = new JLabel("Spurious (present in Response but not in Key): " +
709 typeCounter[SPURIOUS_TYPE]);
710 jLabel.setForeground(BLACK);
711 jLabel.setBackground(colors[SPURIOUS_TYPE]);
712 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
713 jLabel.setOpaque(true);
714 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
715 box.add(jLabel);
716
717 infoBox.add(box);
718 infoBox.add(Box.createRigidArea(new Dimension(40,0)));
720
721 box = new Box(BoxLayout.Y_AXIS);
724
725 jLabel = new JLabel("Precision strict: " +
726 formatter.format(precisionStrict));
727 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
728 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
729 box.add(jLabel);
730
731 jLabel = new JLabel("Precision average: " +
732 formatter.format(precisionAverage));
733 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
734 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
735 box.add(jLabel);
736
737 jLabel = new JLabel("Precision lenient: " +
738 formatter.format(precisionLenient));
739 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
740 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
741 box.add(jLabel);
742
743 infoBox.add(box);
744 infoBox.add(Box.createRigidArea(new Dimension(40,0)));
746
747 box = new Box(BoxLayout.Y_AXIS);
750
751 jLabel = new JLabel("Recall strict: " + formatter.format(recallStrict));
752 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
753 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
754 box.add(jLabel);
755
756 jLabel = new JLabel("Recall average: " + formatter.format(recallAverage));
757 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
758 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
759 box.add(jLabel);
760
761 jLabel = new JLabel("Recall lenient: " + formatter.format(recallLenient));
762 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
763 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
764 box.add(jLabel);
765
766 infoBox.add(box);
767 infoBox.add(Box.createRigidArea(new Dimension(40,0)));
769
770 box = new Box(BoxLayout.Y_AXIS);
773
774 jLabel = new JLabel("F-Measure strict: " +
775 formatter.format(fMeasureStrict));
776 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
777 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
778 box.add(jLabel);
779
780 jLabel = new JLabel("F-Measure average: " +
781 formatter.format(fMeasureAverage));
782 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
783 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
784 box.add(jLabel);
785
786 jLabel = new JLabel("F-Measure lenient: " +
787 formatter.format(fMeasureLenient));
788 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
789 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
790 box.add(jLabel);
791 infoBox.add(box);
792
793 infoBox.add(Box.createRigidArea(new Dimension(40,0)));
795
796 box = new Box(BoxLayout.Y_AXIS);
799
800 jLabel = new JLabel("False positive strict: " +
801 formatter.format(falsePositiveStrict));
802 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
803 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
804 box.add(jLabel);
805
806 jLabel = new JLabel("False positive average: " +
807 formatter.format(falsePositiveAverage));
808 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
809 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
810 box.add(jLabel);
811
812 jLabel = new JLabel("False positive lenient: " +
813 formatter.format(falsePositiveLenient));
814 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
815 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD));
816 box.add(jLabel);
817 infoBox.add(box);
818
819 infoBox.add(Box.createRigidArea(new Dimension(10,0)));
821
822 this.add(infoBox);
823 }
825
826 protected void printStructure(Set aDiffSet){
827 Iterator iterator = aDiffSet.iterator();
828 String leftAnnot = null;
829 String rightAnnot = null;
830 while(iterator.hasNext()){
831 DiffSetElement diffElem = (DiffSetElement) iterator.next();
832 if (diffElem.getLeftAnnotation() == null)
833 leftAnnot = "NULL ";
834 else
835 leftAnnot = diffElem.getLeftAnnotation().toString();
836 if (diffElem.getRightAnnotation() == null)
837 rightAnnot = " NULL";
838 else
839 rightAnnot = diffElem.getRightAnnotation().toString();
840 Out.prln( leftAnnot + "|" + rightAnnot);
841 } }
844
852 protected void doDiff(java.util.List aKeyAnnotList,
853 java.util.List aResponseAnnotList){
854
855 if (aKeyAnnotList == null || aResponseAnnotList == null)
857 return;
858
859 int responseSize = aResponseAnnotList.size();
860
861 Iterator keyIterator = aKeyAnnotList.iterator();
864 while(keyIterator.hasNext()){
865 Annotation keyAnnot = (Annotation) keyIterator.next();
866 Iterator responseIterator = aResponseAnnotList.iterator();
867
868 DiffSetElement diffElement = null;
869 while(responseIterator.hasNext()){
870 Annotation responseAnnot = (Annotation) responseIterator.next();
871
872 if(keyAnnot.isPartiallyCompatible(responseAnnot,keyFeatureNamesSet)){
873 keyPartiallySet.add(keyAnnot);
874 responsePartiallySet.add(responseAnnot);
875 if (keyAnnot.coextensive(responseAnnot)){
876 diffElement = new DiffSetElement( keyAnnot,
879 responseAnnot,
880 DEFAULT_TYPE,
881 CORRECT_TYPE,
882 keyDocument,
883 responseDocument);
884
885 addToDiffset(diffElement);
887 } }else if (keyAnnot.coextensive(responseAnnot)){
889 diffElement = new DiffSetElement( keyAnnot,
893 responseAnnot,
894 detectKeyType(keyAnnot),
895 detectResponseType(responseAnnot),
896 keyDocument,
897 responseDocument);
898 addToDiffset(diffElement);
900 }
902 if (diffElement != null){
903 responseIterator.remove();
905 break;
906 } }
909 if (diffElement == null){
911 if (keyPartiallySet.contains(keyAnnot))
912 diffElement = new DiffSetElement( keyAnnot,
913 null,
914 DEFAULT_TYPE,
915 NULL_TYPE,
916 keyDocument,
917 responseDocument);
918 else{
919 Iterator respParIter = diffSet.iterator();
924 while (respParIter.hasNext()){
925 DiffSetElement diffElem = (DiffSetElement) respParIter.next();
926 Annotation respAnnot = diffElem.getRightAnnotation();
927 if (respAnnot != null && keyAnnot.isPartiallyCompatible(respAnnot,
928 keyFeatureNamesSet)){
929 diffElement = new DiffSetElement( keyAnnot,
930 null,
931 DEFAULT_TYPE,
932 NULL_TYPE,
933 keyDocument,
934 responseDocument);
935 break;
936 } } if (diffElement == null)
940 diffElement = new DiffSetElement( keyAnnot,
941 null,
942 MISSING_TYPE,
943 NULL_TYPE,
944 keyDocument,
945 responseDocument);
946 } addToDiffset(diffElement);
948 }
950 keyIterator.remove();
951 }
953 DiffSetElement diffElem = null;
954 Iterator responseIter = aResponseAnnotList.iterator();
955 while (responseIter.hasNext()){
956 Annotation respAnnot = (Annotation) responseIter.next();
957 if (responsePartiallySet.contains(respAnnot))
958 diffElem = new DiffSetElement( null,
959 respAnnot,
960 NULL_TYPE,
961 PARTIALLY_CORRECT_TYPE,
962 keyDocument,
963 responseDocument);
964 else
965 diffElem = new DiffSetElement( null,
966 respAnnot,
967 NULL_TYPE,
968 SPURIOUS_TYPE,
969 keyDocument,
970 responseDocument);
971 addToDiffset(diffElem);
972 responseIter.remove();
973 }
975 int possible = typeCounter[CORRECT_TYPE] + typeCounter[PARTIALLY_CORRECT_TYPE] + typeCounter[MISSING_TYPE];
981 int actual = typeCounter[CORRECT_TYPE] + typeCounter[PARTIALLY_CORRECT_TYPE] + typeCounter[SPURIOUS_TYPE];
990 if (actual != 0){
991 precisionStrict = ((double)typeCounter[CORRECT_TYPE])/((double)actual);
992 precisionLenient = ((double)(typeCounter[CORRECT_TYPE] +
993 typeCounter[PARTIALLY_CORRECT_TYPE]))/((double)actual);
994 precisionAverage = ((double)(precisionStrict + precisionLenient)) /
995 ((double) 2);
996 } if (possible != 0){
998 recallStrict = ((double)typeCounter[CORRECT_TYPE])/((double)possible);
999 recallLenient = ((double)(typeCounter[CORRECT_TYPE] +
1000 typeCounter[PARTIALLY_CORRECT_TYPE]))/((double)possible);
1001 recallAverage = ((double)(recallStrict + recallLenient)) / ((double)2);
1002 }
1004
1005 int no = 0;
1006 if (annotationTypeForFalsePositive != null)
1009 if (responseAnnotationSetNameFalsePoz == null){
1011 AnnotationSet aSet = responseDocument.getAnnotations().get(
1012 annotationTypeForFalsePositive);
1013 no = aSet == null ? 0 : aSet.size();
1014 }else{
1015 AnnotationSet aSet = responseDocument.getAnnotations(responseAnnotationSetNameFalsePoz).get(
1016 annotationTypeForFalsePositive);
1017 no = aSet == null? 0 : aSet.size();
1018 }
1019 if (no != 0){
1020 falsePositiveStrict = ((double)(typeCounter[SPURIOUS_TYPE] +
1022 typeCounter[PARTIALLY_CORRECT_TYPE])) /((double)no);
1023 falsePositiveLenient = ((double)typeCounter[SPURIOUS_TYPE]) /((double) no);
1024 falsePositiveAverage = ((double)(falsePositiveStrict +
1025 falsePositiveLenient))/((double)2) ;
1026 }
1028 double denominator = weight * (precisionStrict + recallStrict);
1030 if (denominator != 0)
1031 fMeasureStrict = (precisionStrict * recallStrict) / denominator ;
1032 else fMeasureStrict = 0.0;
1033 denominator = weight * (precisionLenient + recallLenient);
1035 if (denominator != 0)
1036 fMeasureLenient = (precisionLenient * recallLenient) / denominator ;
1037 else fMeasureLenient = 0.0;
1038 fMeasureAverage = (fMeasureStrict + fMeasureLenient) / (double)2;
1040
1041 }
1043
1048 private int detectKeyType(Annotation anAnnot){
1049 if (anAnnot == null) return NULL_TYPE;
1050
1051 if (keyPartiallySet.contains(anAnnot)) return DEFAULT_TYPE;
1052 Iterator iter = responsePartiallySet.iterator();
1053 while(iter.hasNext()){
1054 Annotation a = (Annotation) iter.next();
1055 if (anAnnot.isPartiallyCompatible(a,keyFeatureNamesSet))
1056 return DEFAULT_TYPE;
1057 }
1059 iter = responseAnnotList.iterator();
1060 while(iter.hasNext()){
1061 Annotation a = (Annotation) iter.next();
1062 if (anAnnot.isPartiallyCompatible(a,keyFeatureNamesSet)){
1063 responsePartiallySet.add(a);
1064 keyPartiallySet.add(anAnnot);
1065 return DEFAULT_TYPE;
1066 } } return MISSING_TYPE;
1069 }
1071
1077 private int detectResponseType(Annotation anAnnot){
1078 if (anAnnot == null) return NULL_TYPE;
1079
1080 if (responsePartiallySet.contains(anAnnot)) return PARTIALLY_CORRECT_TYPE;
1081 Iterator iter = keyPartiallySet.iterator();
1082 while(iter.hasNext()){
1083 Annotation a = (Annotation) iter.next();
1084 if (a.isPartiallyCompatible(anAnnot,keyFeatureNamesSet))
1085 return PARTIALLY_CORRECT_TYPE;
1086 }
1088 iter = keyAnnotList.iterator();
1089 while(iter.hasNext()){
1090 Annotation a = (Annotation) iter.next();
1091 if (a.isPartiallyCompatible(anAnnot,keyFeatureNamesSet)){
1092 responsePartiallySet.add(anAnnot);
1093 keyPartiallySet.add(a);
1094 return PARTIALLY_CORRECT_TYPE;
1095 } } return SPURIOUS_TYPE;
1098 }
1100
1103 private void addToDiffset(DiffSetElement aDiffSetElement){
1104 if (aDiffSetElement == null) return;
1105
1106 diffSet.add(aDiffSetElement);
1107 if (NULL_TYPE != aDiffSetElement.getRightType())
1110 typeCounter[aDiffSetElement.getRightType()]++;
1111 if (NULL_TYPE != aDiffSetElement.getLeftType() &&
1113 CORRECT_TYPE != aDiffSetElement.getLeftType())
1114 typeCounter[aDiffSetElement.getLeftType()]++;
1115 }
1117
1120
1121
1126 protected class AnnotationDiffTableModel extends AbstractTableModel{
1127
1128
1129 public AnnotationDiffTableModel(Collection data){
1130 modelData = new ArrayList();
1131 modelData.addAll(data);
1132 }
1134
1135 public AnnotationDiffTableModel(){
1136 modelData = new ArrayList();
1137 }
1139
1140 public int getRowCount(){
1141 return modelData.size();
1142 }
1144
1145 public int getColumnCount(){
1146 return 10;
1147 }
1149
1150 public String getColumnName(int column){
1151 switch(column){
1152 case 0: return "String - Key";
1153 case 1: return "Start - Key";
1154 case 2: return "End - Key";
1155 case 3: return "Features - Key";
1156 case 4: return " ";
1157 case 5: return "String - Response";
1158 case 6: return "Start - Response";
1159 case 7: return "End -Response";
1160 case 8: return "Features - Response";
1161 case 9: return "Document";
1162 default:return "?";
1163 }
1164 }
1166
1167 public Class getColumnClass(int column){
1168 switch(column){
1169 case 0: return String.class;
1170 case 1: return Long.class;
1171 case 2: return Long.class;
1172 case 3: return String.class;
1173 case 4: return String.class;
1174 case 5: return String.class;
1175 case 6: return Long.class;
1176 case 7: return Long.class;
1177 case 8: return String.class;
1178 case 9: return String.class;
1179 default:return Object.class;
1180 }
1181 }
1183
1184 public Object getValueAt(int row, int column){
1185 DiffSetElement diffSetElement = (DiffSetElement) modelData.get(row);
1186 if (diffSetElement == null) return null;
1187 switch(column){
1188 case 0:{
1191 if (diffSetElement.getLeftAnnotation() == null) return null;
1192 Annotation annot = diffSetElement.getLeftAnnotation();
1194 String theString = "";
1195 try {
1196 theString = diffSetElement.getKeyDocument().getContent().getContent(
1197 annot.getStartNode().getOffset(),
1198 annot.getEndNode().getOffset()).toString();
1199 } catch (gate.util.InvalidOffsetException ex) {
1200 Err.prln(ex.getMessage());
1201 }
1202 return theString;
1203 }
1204 case 1:{
1206 if (diffSetElement.getLeftAnnotation() == null) return null;
1207 return diffSetElement.getLeftAnnotation().getStartNode().getOffset();
1208 }
1209 case 2:{
1211 if (diffSetElement.getLeftAnnotation() == null) return null;
1212 return diffSetElement.getLeftAnnotation().getEndNode().getOffset();
1213 }
1214 case 3:{
1216 if (diffSetElement.getLeftAnnotation() == null) return null;
1217 if (diffSetElement.getLeftAnnotation().getFeatures() == null)
1218 return null;
1219 return diffSetElement.getLeftAnnotation().getFeatures().toString();
1220 }
1221 case 4:{
1223 return " ";
1224 }
1225 case 5:{
1228 if (diffSetElement.getRightAnnotation() == null) return null;
1229 Annotation annot = diffSetElement.getRightAnnotation();
1231 String theString = "";
1232 try {
1233 theString = diffSetElement.getResponseDocument().getContent().getContent(
1234 annot.getStartNode().getOffset(),
1235 annot.getEndNode().getOffset()).toString();
1236 } catch (gate.util.InvalidOffsetException ex) {
1237 Err.prln(ex.getMessage());
1238 }
1239 return theString;
1240 }
1241 case 6:{
1243 if (diffSetElement.getRightAnnotation() == null) return null;
1244 return diffSetElement.getRightAnnotation().getStartNode().getOffset();
1245 }
1246 case 7:{
1248 if (diffSetElement.getRightAnnotation() == null) return null;
1249 return diffSetElement.getRightAnnotation().getEndNode().getOffset();
1250 }
1251 case 8:{
1253 if (diffSetElement.getRightAnnotation() == null) return null;
1254 return diffSetElement.getRightAnnotation().getFeatures().toString();
1255 }
1256 case 9:{
1258 return diffSetElement.getKeyDocument().getName();
1259 }
1260 case 10:{
1262 return diffSetElement;
1263 }
1264 default:{return null;}
1265 } }
1268 public Object getRawObject(int row){
1269 return modelData.get(row);
1270 }
1272
1273 private java.util.List modelData = null;
1274
1275 }
1277
1280
1283 public class AnnotationDiffCellRenderer extends DefaultTableCellRenderer{
1284
1285
1286 public AnnotationDiffCellRenderer() { }
1288 private Color background = WHITE;
1289
1290 private Color foreground = BLACK;
1291
1292
1293
1294 public Component getTableCellRendererComponent(
1295 JTable table, Object value, boolean isSelected, boolean hasFocus,
1296 int row, int column
1297 ) {
1298 JComponent defaultComp = null;
1299 defaultComp = (JComponent) super.getTableCellRendererComponent(
1300 table, value, isSelected, hasFocus, row, column
1301 );
1302
1303 if (column == 4 || value == null)
1305 return new JPanel();
1306
1307 if (!(table.getModel().getValueAt(row,10) instanceof DiffSetElement))
1308 return defaultComp;
1309
1310 DiffSetElement diffSetElement =
1311 (DiffSetElement) table.getModel().getValueAt(row,10);
1312
1313 if (diffSetElement == null)
1314 return defaultComp;
1315
1316 if (column < 4){
1317 if (NULL_TYPE != diffSetElement.getLeftType())
1318 background = colors[diffSetElement.getLeftType()];
1319 else return new JPanel();
1320 }else if (column < 10){
1321 if (NULL_TYPE != diffSetElement.getRightType())
1322 background = colors[diffSetElement.getRightType()];
1323 else return new JPanel();
1324 }
1325
1326 defaultComp.setBackground(background);
1327 defaultComp.setForeground(BLACK);
1328
1329 defaultComp.setOpaque(true);
1330 return defaultComp;
1331 }
1333 }
1335
1338 class AnnotationSetComparator implements java.util.Comparator {
1339
1340 public AnnotationSetComparator(){}
1341
1342 public int compare(Object o1, Object o2) {
1343 if ( !(o1 instanceof gate.Annotation) ||
1344 !(o2 instanceof gate.Annotation)) return 0;
1345
1346 gate.Annotation a1 = (gate.Annotation) o1;
1347 gate.Annotation a2 = (gate.Annotation) o2;
1348
1349 Long l1 = a1.getStartNode().getOffset();
1350 Long l2 = a2.getStartNode().getOffset();
1351 if (l1 != null)
1352 return l1.compareTo(l2);
1353 else
1354 return -1;
1355 } }
1358
1361
1362
1366 protected class DiffSetElement {
1367
1368 private Annotation leftAnnotation = null;
1369
1370 private Annotation rightAnnotation = null;
1371
1372 private int leftType = DEFAULT_TYPE;
1373
1374 private int rightType = DEFAULT_TYPE;
1375
1376 private Document keyDocument;
1377
1378 private Document respDocument;
1379
1380
1381 public DiffSetElement() {}
1382
1383
1384 public DiffSetElement( Annotation aLeftAnnotation,
1385 Annotation aRightAnnotation,
1386 int aLeftType,
1387 int aRightType){
1388 leftAnnotation = aLeftAnnotation;
1389 rightAnnotation = aRightAnnotation;
1390 leftType = aLeftType;
1391 rightType = aRightType;
1392 keyDocument = null;
1393 respDocument = null;
1394 }
1396
1397 public DiffSetElement( Annotation aLeftAnnotation,
1398 Annotation aRightAnnotation,
1399 int aLeftType,
1400 int aRightType,
1401 Document kDocument,
1402 Document rDocument){
1403 leftAnnotation = aLeftAnnotation;
1404 rightAnnotation = aRightAnnotation;
1405 leftType = aLeftType;
1406 rightType = aRightType;
1407 keyDocument = kDocument;
1408 respDocument = rDocument;
1409 }
1411
1412 public void setLeftAnnotation(Annotation aLeftAnnotation){
1413 leftAnnotation = aLeftAnnotation;
1414 }
1416
1417 public Annotation getLeftAnnotation(){
1418 return leftAnnotation;
1419 }
1421
1422 public void setRightAnnotation(Annotation aRightAnnotation){
1423 rightAnnotation = aRightAnnotation;
1424 }
1426
1427 public Annotation getRightAnnotation(){
1428 return rightAnnotation;
1429 }
1431
1432 public void setLeftType(int aLeftType){
1433 leftType = aLeftType;
1434 }
1436
1437 public int getLeftType() {
1438 return leftType;
1439 }
1441
1442 public void setRightType(int aRightType) {
1443 rightType = aRightType;
1444 }
1446
1447 public int getRightType() {
1448 return rightType;
1449 }
1451
1452 public Document getKeyDocument() {
1453 return keyDocument;
1454 }
1456
1457 public void setKeyDocument(Document aDoc) {
1458 keyDocument = aDoc;
1459 }
1461
1462 public Document getResponseDocument() {
1463 return respDocument;
1464 }
1466
1467 public void setResponseDocument(Document aDoc) {
1468 respDocument = aDoc;
1469 } } }