You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opennlp.apache.org by jz...@apache.org on 2023/01/02 14:01:06 UTC

[opennlp] branch main updated: OPENNLP-1432 Provide tests for opennlp.tools.util.wordvector package (#478)

This is an automated email from the ASF dual-hosted git repository.

jzemerick pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opennlp.git


The following commit(s) were added to refs/heads/main by this push:
     new c79fe28a OPENNLP-1432 Provide tests for opennlp.tools.util.wordvector package (#478)
c79fe28a is described below

commit c79fe28a39f41e372e6ebc160df6e450144518a0
Author: Martin Wiesner <ma...@users.noreply.github.com>
AuthorDate: Mon Jan 2 15:01:01 2023 +0100

    OPENNLP-1432 Provide tests for opennlp.tools.util.wordvector package (#478)
    
    - adds unit tests for each class in `opennlp.tools.util.wordvector`
    - adds related Glove test resources
    - improves existing documentation for details and/or clarity
---
 .../tools/util/wordvector/DoubleArrayVector.java   |  4 +
 .../tools/util/wordvector/FloatArrayVector.java    |  4 +
 .../java/opennlp/tools/util/wordvector/Glove.java  |  7 +-
 .../tools/util/wordvector/MapWordVectorTable.java  |  7 ++
 .../util/wordvector/AbstractWordVectorTest.java}   | 36 ++------
 .../util/wordvector/DoubleArrayVectorTest.java     | 92 +++++++++++++++++++++
 .../util/wordvector/FloatArrayVectorTest.java      | 92 +++++++++++++++++++++
 .../opennlp/tools/util/wordvector/GloveTest.java   | 65 +++++++++++++++
 .../util/wordvector/MapWordVectorTableTest.java    | 96 ++++++++++++++++++++++
 .../wordvector/glove-example-broken-dimensions.txt |  2 +
 .../tools/util/wordvector/glove-example-empty.txt  |  0
 .../tools/util/wordvector/glove-example-short.txt  |  4 +
 12 files changed, 377 insertions(+), 32 deletions(-)

diff --git a/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/DoubleArrayVector.java b/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/DoubleArrayVector.java
index e00ab808..8b8fe032 100644
--- a/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/DoubleArrayVector.java
+++ b/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/DoubleArrayVector.java
@@ -20,6 +20,10 @@ package opennlp.tools.util.wordvector;
 import java.nio.DoubleBuffer;
 import java.nio.FloatBuffer;
 
+/**
+ * A {@link WordVector} implementation that represents the vector as array
+ * of {@code double} values.
+ */
 class DoubleArrayVector implements WordVector {
 
   private final double[] vector;
diff --git a/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/FloatArrayVector.java b/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/FloatArrayVector.java
index a0fd13e9..f528b8fc 100644
--- a/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/FloatArrayVector.java
+++ b/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/FloatArrayVector.java
@@ -20,6 +20,10 @@ package opennlp.tools.util.wordvector;
 import java.nio.DoubleBuffer;
 import java.nio.FloatBuffer;
 
+/**
+ * A {@link WordVector} implementation that represents the vector as array
+ * of {@code float} values.
+ */
 class FloatArrayVector implements WordVector {
 
   private final float[] vector;
diff --git a/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/Glove.java b/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/Glove.java
index a026162c..c0eacefe 100644
--- a/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/Glove.java
+++ b/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/Glove.java
@@ -29,6 +29,9 @@ import java.util.Map;
 import opennlp.tools.util.java.Experimental;
 
 /**
+ *
+ * GloVe is an unsupervised learning algorithm for obtaining vector representations for words.
+ * Details are found on this <a href="https://nlp.stanford.edu/projects/glove/"> web site</a>.
  * <p>
  * Warning: Experimental new feature, see OPENNLP-1144 for details, the API might be changed anytime.
  */
@@ -41,8 +44,8 @@ public class Glove {
   /**
    * Parses a glove vector plain text file.
    * <p>
-   * @param in the input stream for Glove vectors
-   * @return a Glove based wv table
+   * @param in A valid, open {@link InputStream} to Glove vectors from.
+   * @return A Glove based {@link WordVectorTable}, guaranteed to be non {@code null}.
    * @throws IOException if any error occurs during parsing
    */
   @Experimental
diff --git a/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/MapWordVectorTable.java b/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/MapWordVectorTable.java
index 11f687f1..29967923 100644
--- a/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/MapWordVectorTable.java
+++ b/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/MapWordVectorTable.java
@@ -20,6 +20,13 @@ package opennlp.tools.util.wordvector;
 import java.util.Iterator;
 import java.util.Map;
 
+/**
+ * A {@link WordVectorTable} implementation that maps tokens to
+ * {@link WordVector word vectors} via a {@link Map}.
+ *
+ * @see WordVector
+ * @see WordVectorTable
+ */
 class MapWordVectorTable implements WordVectorTable {
 
   private final Map<String, WordVector> vectors;
diff --git a/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/MapWordVectorTable.java b/opennlp-tools/src/test/java/opennlp/tools/util/wordvector/AbstractWordVectorTest.java
similarity index 56%
copy from opennlp-tools/src/main/java/opennlp/tools/util/wordvector/MapWordVectorTable.java
copy to opennlp-tools/src/test/java/opennlp/tools/util/wordvector/AbstractWordVectorTest.java
index 11f687f1..a14f80b4 100644
--- a/opennlp-tools/src/main/java/opennlp/tools/util/wordvector/MapWordVectorTable.java
+++ b/opennlp-tools/src/test/java/opennlp/tools/util/wordvector/AbstractWordVectorTest.java
@@ -17,39 +17,15 @@
 
 package opennlp.tools.util.wordvector;
 
-import java.util.Iterator;
-import java.util.Map;
+import java.io.InputStream;
 
-class MapWordVectorTable implements WordVectorTable {
+import opennlp.tools.formats.AbstractFormatTest;
 
-  private final Map<String, WordVector> vectors;
+public class AbstractWordVectorTest {
 
-  MapWordVectorTable(Map<String, WordVector> vectors) {
-    this.vectors = vectors;
-  }
-
-  @Override
-  public WordVector get(String token) {
-    return vectors.get(token);
-  }
-
-  @Override
-  public Iterator<String> tokens() {
-    return vectors.keySet().iterator();
-  }
-
-  @Override
-  public int size() {
-    return vectors.size();
-  }
+  protected static final String FORMATS_BASE_DIR = "/opennlp/tools/util/wordvector/";
 
-  @Override
-  public int dimension() {
-    if (vectors.size() > 0) {
-      return vectors.values().iterator().next().dimension();
-    }
-    else {
-      return -1;
-    }
+  protected InputStream getResourceStream(String resource) {
+    return AbstractFormatTest.class.getResourceAsStream(FORMATS_BASE_DIR + resource);
   }
 }
diff --git a/opennlp-tools/src/test/java/opennlp/tools/util/wordvector/DoubleArrayVectorTest.java b/opennlp-tools/src/test/java/opennlp/tools/util/wordvector/DoubleArrayVectorTest.java
new file mode 100644
index 00000000..4151b3a7
--- /dev/null
+++ b/opennlp-tools/src/test/java/opennlp/tools/util/wordvector/DoubleArrayVectorTest.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package opennlp.tools.util.wordvector;
+
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class DoubleArrayVectorTest {
+
+  private double[] doubleArray;
+
+  @BeforeEach
+  public void setup() {
+    doubleArray = new double[]{Float.MIN_VALUE, -1, 0, 1, Float.MAX_VALUE};
+  }
+
+  @AfterEach
+  public void tearDown() {
+    doubleArray = null;
+  }
+
+  @Test
+  public void testGetDataType() {
+    DoubleArrayVector faVector = new DoubleArrayVector(doubleArray);
+    Assertions.assertEquals(WordVectorType.DOUBLE, faVector.getDataType());
+  }
+
+  @Test
+  public void testGetDimension() {
+    DoubleArrayVector faVector = new DoubleArrayVector(doubleArray);
+    Assertions.assertEquals(doubleArray.length, faVector.dimension());
+  }
+
+  @Test
+  public void testGetAsFloat() {
+    DoubleArrayVector faVector = new DoubleArrayVector(doubleArray);
+    for (int i = 0; i < faVector.dimension(); i++) {
+      Assertions.assertEquals(doubleArray[i], faVector.getAsFloat(i));
+    }
+  }
+
+  @Test
+  public void testGetAsDouble() {
+    DoubleArrayVector faVector = new DoubleArrayVector(doubleArray);
+    for (int i = 0; i < faVector.dimension(); i++) {
+      Assertions.assertEquals(doubleArray[i], faVector.getAsDouble(i));
+    }
+  }
+
+  @Test
+  public void testToFloatBuffer() {
+    // reference
+    final float[] floatArray = new float[]{Float.MIN_VALUE, -1, 0, 1, Float.MAX_VALUE};
+    FloatBuffer refBuffer = FloatBuffer.wrap(floatArray);
+
+    DoubleArrayVector daVector = new DoubleArrayVector(doubleArray);
+    FloatBuffer fBuffer = daVector.toFloatBuffer();
+    Assertions.assertNotNull(fBuffer);
+    Assertions.assertEquals(0, refBuffer.compareTo(fBuffer));
+  }
+
+  @Test
+  public void testToDoubleBuffer() {
+    // reference
+    DoubleBuffer refBuffer = DoubleBuffer.wrap(doubleArray);
+
+    DoubleArrayVector daVector = new DoubleArrayVector(this.doubleArray);
+    DoubleBuffer dBuffer = daVector.toDoubleBuffer();
+    Assertions.assertNotNull(dBuffer);
+    Assertions.assertEquals(0, refBuffer.compareTo(dBuffer));
+  }
+}
diff --git a/opennlp-tools/src/test/java/opennlp/tools/util/wordvector/FloatArrayVectorTest.java b/opennlp-tools/src/test/java/opennlp/tools/util/wordvector/FloatArrayVectorTest.java
new file mode 100644
index 00000000..f451950b
--- /dev/null
+++ b/opennlp-tools/src/test/java/opennlp/tools/util/wordvector/FloatArrayVectorTest.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package opennlp.tools.util.wordvector;
+
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class FloatArrayVectorTest {
+
+  private float[] floatArray;
+
+  @BeforeEach
+  public void setup() {
+    floatArray = new float[]{Float.MIN_VALUE, -1, 0, 1, Float.MAX_VALUE};
+  }
+
+  @AfterEach
+  public void tearDown() {
+    floatArray = null;
+  }
+
+  @Test
+  public void testGetDataType() {
+    FloatArrayVector faVector = new FloatArrayVector(floatArray);
+    Assertions.assertEquals(WordVectorType.FLOAT, faVector.getDataType());
+  }
+
+  @Test
+  public void testGetDimension() {
+    FloatArrayVector faVector = new FloatArrayVector(floatArray);
+    Assertions.assertEquals(floatArray.length, faVector.dimension());
+  }
+
+  @Test
+  public void testGetAsFloat() {
+    FloatArrayVector faVector = new FloatArrayVector(floatArray);
+    for (int i = 0; i < faVector.dimension(); i++) {
+      Assertions.assertEquals(floatArray[i], faVector.getAsFloat(i));
+    }
+  }
+
+  @Test
+  public void testGetAsDouble() {
+    FloatArrayVector faVector = new FloatArrayVector(floatArray);
+    for (int i = 0; i < faVector.dimension(); i++) {
+      Assertions.assertEquals(floatArray[i], faVector.getAsDouble(i));
+    }
+  }
+
+  @Test
+  public void testToFloatBuffer() {
+    // reference
+    FloatBuffer refBuffer = FloatBuffer.wrap(floatArray);
+
+    FloatArrayVector faVector = new FloatArrayVector(floatArray);
+    FloatBuffer fBuffer = faVector.toFloatBuffer();
+    Assertions.assertNotNull(fBuffer);
+    Assertions.assertEquals(0, refBuffer.compareTo(fBuffer));
+  }
+
+  @Test
+  public void testToDoubleBuffer() {
+    // reference
+    final double[] doubleArray = new double[]{Float.MIN_VALUE, -1, 0, 1, Float.MAX_VALUE};
+    DoubleBuffer refBuffer = DoubleBuffer.wrap(doubleArray);
+
+    FloatArrayVector faVector = new FloatArrayVector(floatArray);
+    DoubleBuffer dBuffer = faVector.toDoubleBuffer();
+    Assertions.assertNotNull(dBuffer);
+    Assertions.assertEquals(0, refBuffer.compareTo(dBuffer));
+  }
+}
diff --git a/opennlp-tools/src/test/java/opennlp/tools/util/wordvector/GloveTest.java b/opennlp-tools/src/test/java/opennlp/tools/util/wordvector/GloveTest.java
new file mode 100644
index 00000000..946fcbbe
--- /dev/null
+++ b/opennlp-tools/src/test/java/opennlp/tools/util/wordvector/GloveTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package opennlp.tools.util.wordvector;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+
+/*
+ * Note:
+ * Examples taken from the 'glove.6B.50d.txt' data set,
+ * which is licensed under CC0 1.0 Universal (CC0 1.0) Public Domain Dedication.
+ * (see: https://creativecommons.org/publicdomain/zero/1.0/)
+ */
+public class GloveTest extends AbstractWordVectorTest {
+
+  @Test
+  public void testParseValid() throws IOException {
+    try (InputStream glove = getResourceStream("glove-example-short.txt")) {
+      WordVectorTable wvTable = Glove.parse(glove);
+      Assertions.assertNotNull(wvTable);
+      Assertions.assertNotNull(wvTable.get("the"));
+      Assertions.assertNotNull(wvTable.get("of"));
+      Assertions.assertNotNull(wvTable.get("to"));
+      Assertions.assertNotNull(wvTable.get("and"));
+
+      // Tokens unknown in the short example should not be found (!)
+      Assertions.assertNull(wvTable.get("OpenNLP"));
+    }
+  }
+
+  @Test
+  public void testParseEmpty() throws IOException {
+    try (InputStream glove = getResourceStream("glove-example-empty.txt")) {
+      WordVectorTable wvTable = Glove.parse(glove);
+      Assertions.assertNotNull(wvTable);
+      Assertions.assertEquals(-1, wvTable.dimension());
+    }
+  }
+
+  @Test
+  public void testParseDetectsBrokenDimensions() throws IOException {
+    try (InputStream glove = getResourceStream("glove-example-broken-dimensions.txt")) {
+      Assertions.assertThrows(IOException.class, () -> Glove.parse(glove));
+    }
+  }
+}
diff --git a/opennlp-tools/src/test/java/opennlp/tools/util/wordvector/MapWordVectorTableTest.java b/opennlp-tools/src/test/java/opennlp/tools/util/wordvector/MapWordVectorTableTest.java
new file mode 100644
index 00000000..56a5fc1d
--- /dev/null
+++ b/opennlp-tools/src/test/java/opennlp/tools/util/wordvector/MapWordVectorTableTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package opennlp.tools.util.wordvector;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class MapWordVectorTableTest extends AbstractWordVectorTest {
+
+  private WordVectorTable wvTable;
+
+  @BeforeEach
+  public void setup() throws IOException {
+    try (InputStream glove = getResourceStream("glove-example-short.txt")) {
+      wvTable = Glove.parse(glove);
+      Assertions.assertNotNull(wvTable);
+    }
+  }
+
+  @Test
+  public void testSize() {
+    // see content of: 'glove-example-short.txt'
+    Assertions.assertEquals(4f,  wvTable.size());
+  }
+
+  @Test
+  public void testDimension() {
+    // see content of: 'glove-example-short.txt'
+    Assertions.assertEquals(50f,  wvTable.dimension());
+  }
+
+  @Test
+  public void testTokens() {
+    // reference
+    Set<String> refTokens = Set.of("the",  "of",  "to",  "and");
+    Iterator<String> tokens = wvTable.tokens();
+    Assertions.assertNotNull(tokens);
+    String token;
+    while (tokens.hasNext()) {
+      token = tokens.next();
+      Assertions.assertTrue(refTokens.contains(token));
+    }
+  }
+
+  @Test
+  public void testGetWordVectors() {
+    // reference
+    Set<String> refTokens = Set.of("the",  "of",  "to",  "and");
+
+    for (String token: refTokens) {
+      WordVector wv = wvTable.get(token);
+      Assertions.assertNotNull(wv);
+      Assertions.assertEquals(50f,  wv.dimension());
+    }
+  }
+
+  @Test
+  public void testGetWordVectorEquality() {
+    // the word vector of "the" token,  see content of: 'glove-example-short.txt'
+    float[] wordVectorOfThe = new float[] {
+        0.418f, 0.24968f, -0.41242f, 0.1217f, 0.34527f, -0.044457f, -0.49688f, -0.17862f,
+        -0.00066023f, -0.6566f, 0.27843f, -0.14767f, -0.55677f, 0.14658f, -0.0095095f,
+        0.011658f, 0.10204f, -0.12792f, -0.8443f, -0.12181f, -0.016801f, -0.33279f, -0.1552f,
+        -0.23131f, -0.19181f, -1.8823f, -0.76746f, 0.099051f, -0.42125f, -0.19526f, 4.0071f,
+        -0.18594f, -0.52287f, -0.31681f, 0.00059213f, 0.0074449f, 0.17778f, -0.15897f, 0.012041f,
+        -0.054223f, -0.29871f, -0.15749f, -0.34758f, -0.045637f, -0.44251f, 0.18785f, 0.0027849f,
+        -0.18411f, -0.11514f, -0.78581f};
+    FloatArrayVector refWordVector = new FloatArrayVector(wordVectorOfThe);
+    WordVector wv = wvTable.get("the");
+    Assertions.assertNotNull(wv);
+    for (int i = 0; i < wordVectorOfThe.length; i++) {
+      Assertions.assertEquals(refWordVector.getAsFloat(i), wv.getAsFloat(i));
+    }
+  }
+}
diff --git a/opennlp-tools/src/test/resources/opennlp/tools/util/wordvector/glove-example-broken-dimensions.txt b/opennlp-tools/src/test/resources/opennlp/tools/util/wordvector/glove-example-broken-dimensions.txt
new file mode 100644
index 00000000..693295b6
--- /dev/null
+++ b/opennlp-tools/src/test/resources/opennlp/tools/util/wordvector/glove-example-broken-dimensions.txt
@@ -0,0 +1,2 @@
+the 0.418 0.24968 -0.41242
+of 0.70853
\ No newline at end of file
diff --git a/opennlp-tools/src/test/resources/opennlp/tools/util/wordvector/glove-example-empty.txt b/opennlp-tools/src/test/resources/opennlp/tools/util/wordvector/glove-example-empty.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/opennlp-tools/src/test/resources/opennlp/tools/util/wordvector/glove-example-short.txt b/opennlp-tools/src/test/resources/opennlp/tools/util/wordvector/glove-example-short.txt
new file mode 100644
index 00000000..ff03e575
--- /dev/null
+++ b/opennlp-tools/src/test/resources/opennlp/tools/util/wordvector/glove-example-short.txt
@@ -0,0 +1,4 @@
+the 0.418 0.24968 -0.41242 0.1217 0.34527 -0.044457 -0.49688 -0.17862 -0.00066023 -0.6566 0.27843 -0.14767 -0.55677 0.14658 -0.0095095 0.011658 0.10204 -0.12792 -0.8443 -0.12181 -0.016801 -0.33279 -0.1552 -0.23131 -0.19181 -1.8823 -0.76746 0.099051 -0.42125 -0.19526 4.0071 -0.18594 -0.52287 -0.31681 0.00059213 0.0074449 0.17778 -0.15897 0.012041 -0.054223 -0.29871 -0.15749 -0.34758 -0.045637 -0.44251 0.18785 0.0027849 -0.18411 -0.11514 -0.78581
+of 0.70853 0.57088 -0.4716 0.18048 0.54449 0.72603 0.18157 -0.52393 0.10381 -0.17566 0.078852 -0.36216 -0.11829 -0.83336 0.11917 -0.16605 0.061555 -0.012719 -0.56623 0.013616 0.22851 -0.14396 -0.067549 -0.38157 -0.23698 -1.7037 -0.86692 -0.26704 -0.2589 0.1767 3.8676 -0.1613 -0.13273 -0.68881 0.18444 0.0052464 -0.33874 -0.078956 0.24185 0.36576 -0.34727 0.28483 0.075693 -0.062178 -0.38988 0.22902 -0.21617 -0.22562 -0.093918 -0.80375
+to 0.68047 -0.039263 0.30186 -0.17792 0.42962 0.032246 -0.41376 0.13228 -0.29847 -0.085253 0.17118 0.22419 -0.10046 -0.43653 0.33418 0.67846 0.057204 -0.34448 -0.42785 -0.43275 0.55963 0.10032 0.18677 -0.26854 0.037334 -2.0932 0.22171 -0.39868 0.20912 -0.55725 3.8826 0.47466 -0.95658 -0.37788 0.20869 -0.32752 0.12751 0.088359 0.16351 -0.21634 -0.094375 0.018324 0.21048 -0.03088 -0.19722 0.082279 -0.09434 -0.073297 -0.064699 -0.26044
+and 0.26818 0.14346 -0.27877 0.016257 0.11384 0.69923 -0.51332 -0.47368 -0.33075 -0.13834 0.2702 0.30938 -0.45012 -0.4127 -0.09932 0.038085 0.029749 0.10076 -0.25058 -0.51818 0.34558 0.44922 0.48791 -0.080866 -0.10121 -1.3777 -0.10866 -0.23201 0.012839 -0.46508 3.8463 0.31362 0.13643 -0.52244 0.3302 0.33707 -0.35601 0.32431 0.12041 0.3512 -0.069043 0.36885 0.25168 -0.24517 0.25381 0.1367 -0.31178 -0.6321 -0.25028 -0.38097
\ No newline at end of file