OSDN Git Service

Fixed an error that StreamAmoebaJoin was case-sensitive to the node name
authorleo <leo@ae02f08e-27ec-0310-ae8c-8ba02fe2eafd>
Thu, 21 May 2009 03:51:26 +0000 (03:51 +0000)
committerleo <leo@ae02f08e-27ec-0310-ae8c-8ba02fe2eafd>
Thu, 21 May 2009 03:51:26 +0000 (03:51 +0000)
git-svn-id: http://www.xerial.org/svn/project/XerialJ/trunk/xerial-core@3325 ae02f08e-27ec-0310-ae8c-8ba02fe2eafd

src/main/java/org/xerial/json/JSONString.java
src/main/java/org/xerial/json/JSONWriter.java
src/main/java/org/xerial/lens/ObjectLens.java
src/main/java/org/xerial/lens/ParameterGetter.java [new file with mode: 0644]
src/main/java/org/xerial/lens/ParameterSetter.java
src/main/java/org/xerial/relation/query/StreamAmoebaJoin.java
src/main/java/org/xerial/silk/SilkStreamReader.java
src/main/java/org/xerial/util/reflect/ReflectionUtil.java
src/test/java/org/xerial/lens/LensTest.java
src/test/java/org/xerial/lens/ObjectLensTest.java
src/test/java/org/xerial/lens/sample.bed.silk

index 84c7816..8412738 100644 (file)
@@ -26,49 +26,57 @@ package org.xerial.json;
 \r
 import org.xerial.util.StringUtil;\r
 \r
+public class JSONString extends JSONValueBase\r
+{\r
 \r
-public class JSONString extends JSONValueBase {\r
+    private String s;\r
 \r
-       private String s;\r
-       public JSONString() {}\r
-       public JSONString(String s)\r
-       {\r
-               this.s = StringUtil.unquote(s);\r
-       }\r
-       \r
-       public String toString()\r
-       {\r
-               return s;\r
-       }\r
-       \r
-       public String toJSONString()\r
-       {\r
-               return "\"" + s + "\"";\r
-       }\r
-       \r
-       @Override\r
-       public boolean equals(Object obj) {\r
-               if (obj instanceof JSONString) {\r
-                       return s.equals(((JSONString) obj).s);\r
-               }\r
-               return false;\r
-       }\r
-       \r
-       @Override\r
-       public JSONString getJSONString() {\r
-               return this;\r
-       }\r
-       \r
-       public String getValue()\r
-       {\r
-               return s;\r
-       }\r
-    public JSONValueType getValueType()\r
+    public JSONString()\r
+    {}\r
+\r
+    public JSONString(String s)\r
     {\r
-        return JSONValueType.String;\r
+        this.s = StringUtil.unquote(s);\r
+    }\r
+\r
+    public String toString()\r
+    {\r
+        return s;\r
+    }\r
+\r
+    public String toJSONString()\r
+    {\r
+        return toJSONString(s);\r
+    }\r
+\r
+    public static String toJSONString(String s)\r
+    {\r
+        return "\"" + s + "\"";\r
     }\r
-}\r
 \r
+    @Override\r
+    public boolean equals(Object obj)\r
+    {\r
+        if (obj instanceof JSONString)\r
+        {\r
+            return s.equals(((JSONString) obj).s);\r
+        }\r
+        return false;\r
+    }\r
 \r
+    @Override\r
+    public JSONString getJSONString()\r
+    {\r
+        return this;\r
+    }\r
 \r
+    public String getValue()\r
+    {\r
+        return s;\r
+    }\r
 \r
+    public JSONValueType getValueType()\r
+    {\r
+        return JSONValueType.String;\r
+    }\r
+}\r
index 84e3b0e..1d2adb1 100644 (file)
@@ -268,7 +268,7 @@ public class JSONWriter
     public void putObject(String key, Object obj)
     {
         if (obj == null)
-            putNull(key);
+            return; // output nothing
         else
         {
             putInternal(key, ObjectLens.toJSON(obj));
index e6d23da..ad088bb 100644 (file)
 //--------------------------------------\r
 package org.xerial.lens;\r
 \r
+import java.io.StringWriter;\r
 import java.lang.reflect.Field;\r
 import java.lang.reflect.Method;\r
 import java.lang.reflect.Modifier;\r
 import java.lang.reflect.Type;\r
 import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
 import java.util.HashMap;\r
 import java.util.List;\r
+import java.util.Map;\r
+import java.util.Map.Entry;\r
 import java.util.regex.Matcher;\r
 import java.util.regex.Pattern;\r
 \r
+import org.xerial.json.JSONString;\r
+import org.xerial.json.JSONWriter;\r
 import org.xerial.util.Pair;\r
 import org.xerial.util.bean.TypeInfo;\r
+import org.xerial.util.log.Logger;\r
 import org.xerial.util.reflect.ReflectionUtil;\r
 \r
 /**\r
@@ -46,6 +54,8 @@ import org.xerial.util.reflect.ReflectionUtil;
  */\r
 public class ObjectLens\r
 {\r
+    private static Logger _logger = Logger.getLogger(ObjectLens.class);\r
+\r
     private static HashMap<Class< ? >, ObjectLens> cache = new HashMap<Class< ? >, ObjectLens>();\r
 \r
     /**\r
@@ -66,17 +76,24 @@ public class ObjectLens
     }\r
 \r
     private Class< ? > targetType;\r
+\r
+    private List<ParameterGetter> getterContainer = new ArrayList<ParameterGetter>();\r
     private List<ParameterSetter> setterContainer = new ArrayList<ParameterSetter>();\r
     private List<RelationSetter> relationSetterContainer = new ArrayList<RelationSetter>();\r
 \r
     public List<ParameterSetter> getSetterList()\r
     {\r
-        return setterContainer;\r
+        return Collections.unmodifiableList(setterContainer);\r
     }\r
 \r
     public List<RelationSetter> getRelationSetterList()\r
     {\r
-        return relationSetterContainer;\r
+        return Collections.unmodifiableList(relationSetterContainer);\r
+    }\r
+\r
+    public List<ParameterGetter> getGetterContainer()\r
+    {\r
+        return Collections.unmodifiableList(getterContainer);\r
     }\r
 \r
     protected ObjectLens(Class< ? > targetType)\r
@@ -90,16 +107,6 @@ public class ObjectLens
         return targetType;\r
     }\r
 \r
-    public void bindParameter(Object target, String parameterName, Object value)\r
-    {\r
-\r
-    }\r
-\r
-    public void bindRelation(Object target, String relationName, Object coreNode, Object attributeNode)\r
-    {\r
-\r
-    }\r
-\r
     @Override\r
     public String toString()\r
     {\r
@@ -112,6 +119,10 @@ public class ObjectLens
         // scan public fields\r
         for (Field eachField : targetType.getFields())\r
         {\r
+            // ignore fields defined in the Object class\r
+            if (eachField.getDeclaringClass() == Object.class)\r
+                continue;\r
+\r
             int fieldModifier = eachField.getModifiers();\r
             if (Modifier.isPublic(fieldModifier) && !Modifier.isTransient(fieldModifier))\r
             {\r
@@ -140,9 +151,13 @@ public class ObjectLens
                     Class< ? > elementType = ReflectionUtil.getRawClass(ReflectionUtil\r
                             .getGenericCollectionElementType(eachField));\r
                     setterContainer.add(ParameterSetter.newSetter(elementType, paramName, eachField));\r
+                    getterContainer.add(ParameterGetter.newFieldGetter(eachField, paramName));\r
                 }\r
                 else\r
+                {\r
                     setterContainer.add(ParameterSetter.newSetter(fieldType, paramName, eachField));\r
+                    getterContainer.add(ParameterGetter.newFieldGetter(eachField, paramName));\r
+                }\r
 \r
             }\r
 \r
@@ -151,8 +166,9 @@ public class ObjectLens
         // scan methods\r
         for (Method eachMethod : targetType.getMethods())\r
         {\r
+\r
             String methodName = eachMethod.getName();\r
-            String paramPart = pickPropertyName(methodName);\r
+            String paramName = pickPropertyName(methodName);\r
 \r
             if (methodName.startsWith("add") || methodName.startsWith("set") || methodName.startsWith("put"))\r
             {\r
@@ -161,13 +177,13 @@ public class ObjectLens
                 {\r
                 case 1:\r
                 {\r
-                    addNewSetter(setterContainer, paramPart, eachMethod);\r
+                    addNewSetter(setterContainer, paramName, eachMethod);\r
                     break;\r
                 }\r
                 case 2:\r
                 {\r
                     // relation adder\r
-                    Pair<String, String> relName = pickRelationName(paramPart);\r
+                    Pair<String, String> relName = pickRelationName(paramName);\r
                     if (relName == null)\r
                     {\r
                         // infer relation node names\r
@@ -186,9 +202,21 @@ public class ObjectLens
             }\r
             else if (methodName.startsWith("append"))\r
             {\r
-                addNewSetter(setterContainer, paramPart, eachMethod);\r
+                addNewSetter(setterContainer, paramName, eachMethod);\r
                 continue;\r
             }\r
+            else if (methodName.startsWith("get"))\r
+            {\r
+                if (eachMethod.getParameterTypes().length == 0)\r
+                {\r
+                    // ignore getters defined in the Object.class\r
+                    if (Object.class == eachMethod.getDeclaringClass())\r
+                        continue;\r
+\r
+                    getterContainer.add(ParameterGetter.newGetter(eachMethod, paramName));\r
+                }\r
+\r
+            }\r
 \r
         }\r
 \r
@@ -241,11 +269,79 @@ public class ObjectLens
                     getCanonicalParameterName(m.group(2)));\r
     }\r
 \r
-    static String getCanonicalParameterName(String paramName)\r
+    static private Pattern paramNameReplacePattern = Pattern.compile("[\\s-_]");\r
+\r
+    public static String getCanonicalParameterName(String paramName)\r
+    {\r
+        Matcher m = paramNameReplacePattern.matcher(paramName);\r
+        return m.replaceAll("").toLowerCase();\r
+    }\r
+\r
+    public static String toJSON(Object obj)\r
     {\r
-        paramName = paramName.replaceAll("\\s", "");\r
-        paramName = paramName.replaceAll("-", "");\r
-        return paramName.toLowerCase();\r
+        if (obj == null)\r
+            return "null";\r
+\r
+        Class< ? > c = obj.getClass();\r
+\r
+        if (TypeInfo.isBasicType(c))\r
+        {\r
+            if (c == String.class)\r
+                return JSONString.toJSONString(obj.toString());\r
+            else\r
+                return obj.toString();\r
+        }\r
+\r
+        StringWriter buf = new StringWriter();\r
+        JSONWriter json = new JSONWriter(buf);\r
+\r
+        toJSON(json, obj);\r
+\r
+        json.flush();\r
+        return buf.toString();\r
+    }\r
+\r
+    private static void toJSON(JSONWriter json, Object obj)\r
+    {\r
+        Class< ? > c = obj.getClass();\r
+\r
+        if (TypeInfo.isCollection(c))\r
+        {\r
+            json.startArray();\r
+            Collection< ? > collection = (Collection< ? >) obj;\r
+            for (Object elem : collection)\r
+            {\r
+                toJSON(json, elem);\r
+            }\r
+            json.endArray();\r
+        }\r
+        else if (TypeInfo.isMap(c))\r
+        {\r
+            json.startArray();\r
+            Map< ? , ? > map = (Map< ? , ? >) obj;\r
+\r
+            json.startArray();\r
+            for (Entry< ? , ? > each : map.entrySet())\r
+            {\r
+                json.startObject();\r
+                json.putObject("key", each.getKey());\r
+                json.putObject("value", each.getValue());\r
+                json.endObject();\r
+            }\r
+            json.endArray();\r
+\r
+            json.endArray();\r
+        }\r
+        else\r
+        {\r
+            ObjectLens lens = getObjectLens(obj.getClass());\r
+            json.startObject();\r
+            for (ParameterGetter getter : lens.getGetterContainer())\r
+            {\r
+                json.putObject(getter.getParamName(), getter.get(obj));\r
+            }\r
+            json.endObject();\r
+        }\r
     }\r
 \r
 }\r
diff --git a/src/main/java/org/xerial/lens/ParameterGetter.java b/src/main/java/org/xerial/lens/ParameterGetter.java
new file mode 100644 (file)
index 0000000..aa7740d
--- /dev/null
@@ -0,0 +1,111 @@
+/*--------------------------------------------------------------------------
+ *  Copyright 2009 Taro L. Saito
+ *
+ *  Licensed 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.
+ *--------------------------------------------------------------------------*/
+//--------------------------------------
+// XerialJ
+//
+// ParameterGetter.java
+// Since: May 21, 2009 11:15:16 AM
+//
+// $URL$
+// $Author$
+//--------------------------------------
+package org.xerial.lens;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.xerial.core.XerialError;
+import org.xerial.core.XerialErrorCode;
+import org.xerial.util.reflect.ReflectionUtil;
+
+/**
+ * For retrieving object parameter values
+ * 
+ * @author leo
+ * 
+ */
+public abstract class ParameterGetter
+{
+    private final String paramName;
+
+    public ParameterGetter(String paramName)
+    {
+        this.paramName = paramName;
+    }
+
+    public String getParamName()
+    {
+        return paramName;
+    }
+
+    public abstract Object get(Object obj);
+
+    public static ParameterGetter newFieldGetter(Field field, String paramName)
+    {
+        return new FieldGetter(field, paramName);
+    }
+
+    public static ParameterGetter newGetter(Method getter, String paramName)
+    {
+        return new GetterMethod(getter, paramName);
+    }
+
+    @Override
+    public String toString()
+    {
+        return paramName;
+    }
+
+    private static class FieldGetter extends ParameterGetter
+    {
+        final Field field;
+
+        public FieldGetter(Field field, String paramName)
+        {
+            super(paramName);
+            this.field = field;
+        }
+
+        @Override
+        public Object get(Object obj)
+        {
+            return ReflectionUtil.getFieldValue(obj, field);
+        }
+    }
+
+    private static class GetterMethod extends ParameterGetter
+    {
+        final Method getter;
+
+        public GetterMethod(Method getter, String paramName)
+        {
+            super(paramName);
+
+            this.getter = getter;
+
+            if (getter.getParameterTypes().length != 0)
+                throw new XerialError(XerialErrorCode.INVALID_INPUT, "not a getter");
+
+        }
+
+        @Override
+        public Object get(Object obj)
+        {
+            return ReflectionUtil.invokeGetter(obj, getter);
+        }
+    }
+
+}
index 0c1cca8..0a9259e 100644 (file)
@@ -99,6 +99,7 @@ public abstract class ParameterSetter
             super(parameterType, parameterName);\r
             this.targetField = targetField;\r
 \r
+            // make the final fields accessible\r
             if (!targetField.isAccessible())\r
                 targetField.setAccessible(true);\r
 \r
@@ -110,6 +111,11 @@ public abstract class ParameterSetter
             ReflectionUtil.setFieldValue(object, targetField, value);\r
         }\r
 \r
+        public Object get(Object object) throws XerialException\r
+        {\r
+            return ReflectionUtil.getFieldValue(object, targetField);\r
+        }\r
+\r
     }\r
 \r
     private static class MethodSetter extends ParameterSetter\r
index b029413..e757d55 100644 (file)
@@ -36,6 +36,7 @@ import java.util.Map.Entry;
 import org.xerial.core.XerialError;
 import org.xerial.core.XerialErrorCode;
 import org.xerial.core.XerialException;
+import org.xerial.lens.ObjectLens;
 import org.xerial.relation.Node;
 import org.xerial.relation.TupleIndex;
 import org.xerial.relation.Node.NodeBuilder;
@@ -352,8 +353,15 @@ public class StreamAmoebaJoin implements TreeVisitor
         return nodeStackOfEachTag.get(nodeName);
     }
 
+    public static String sanitize(String nodeName)
+    {
+        return ObjectLens.getCanonicalParameterName(nodeName);
+    }
+
     public void visitNode(String nodeName, String nodeValue, TreeWalker walker) throws XerialException
     {
+        nodeName = sanitize(nodeName);
+
         Node currentNode = new NodeBuilder(nodeName).nodeID(++nodeCount).nodeValue(nodeValue).build();
         Deque<Node> nodeStack = getNodeStack(nodeName);
         nodeStack.add(currentNode);
@@ -378,6 +386,8 @@ public class StreamAmoebaJoin implements TreeVisitor
 
     public void text(String nodeName, String textDataFragment, TreeWalker walker) throws XerialException
     {
+        nodeName = sanitize(nodeName);
+
         Iterator<LatticeNode<String>> it = stateStack.descendingIterator();
         LatticeNode<String> currentState = it.next();
         LatticeNode<String> prevState = it.next();
@@ -423,6 +433,8 @@ public class StreamAmoebaJoin implements TreeVisitor
 
     public void leaveNode(String nodeName, TreeWalker walker) throws XerialException
     {
+        nodeName = sanitize(nodeName);
+
         Deque<Node> nodeStack = getNodeStack(nodeName);
         Node currentNode = nodeStack.getLast();
 
index c0f376b..bb9915c 100644 (file)
@@ -59,6 +59,7 @@ import org.xerial.silk.plugin.SilkFunctionArgument;
 import org.xerial.silk.plugin.SilkFunctionPlugin;\r
 import org.xerial.util.ArrayDeque;\r
 import org.xerial.util.FileResource;\r
+import org.xerial.util.StringUtil;\r
 import org.xerial.util.bean.TypeInfo;\r
 import org.xerial.util.log.Logger;\r
 import org.xerial.util.reflect.ReflectionUtil;\r
@@ -609,7 +610,7 @@ public class SilkStreamReader implements TreeStreamReader
             }\r
             else\r
             {\r
-                visit(node.getName(), columnData);\r
+                visit(node.getName(), StringUtil.unquote(columnData));\r
                 leave(node.getName());\r
             }\r
         }\r
index d99c6d8..79a0390 100644 (file)
@@ -110,6 +110,26 @@ public class ReflectionUtil
         return value;
     }
 
+    public static Object invokeGetter(Object bean, Method getter)
+    {
+        try
+        {
+            return getter.invoke(bean);
+        }
+        catch (IllegalArgumentException e)
+        {
+            throw new XerialError(XerialErrorCode.INVALID_STATE, "not a getter (0-arg public method): " + getter);
+        }
+        catch (IllegalAccessException e)
+        {
+            throw new IllegalAccessError(e.getMessage());
+        }
+        catch (InvocationTargetException e)
+        {
+            throw new XerialError(XerialErrorCode.WRONG_DATA_TYPE, e);
+        }
+    }
+
     /**
      * Get the generic element type of the field that has a collection type. For
      * example, for a field <em>f</em>
index a6ad4e1..a406186 100644 (file)
@@ -111,10 +111,18 @@ public class LensTest
     @Test
     public void testBED() throws Exception
     {
-        BEDQuery result = new BEDQuery("chr22", 1L, 10000L);
+        BEDQuery result = new BEDQuery("chr7", 1L, 1000000000L);
         Lens.loadSilk(result, FileResource.find(LensTest.class, "sample.bed.silk"));
 
         _logger.info(StringUtil.join(result.geneList, "\n"));
+
+        assertEquals("Item,RGB,Demo2", result.track.name);
+        assertEquals("Item RGBdemonstration2", result.track.description);
+        assertEquals(2, result.track.visibility);
+        assertEquals("On", result.track.itemRgb);
+        assertEquals(1, result.track.useScore);
+        assertEquals("0,128,0", result.track.color);
+        assertEquals("http://genome.ucsc.edu/goldenPath/help/clones.html#$$", result.track.url);
     }
 
     public static class Locus
@@ -157,23 +165,37 @@ public class LensTest
     {
         public String coordinate;
         public String name;
+        public String color;
+        public String strand;
         public List<CDS> cds;
         public List<Exon> exon;
 
         @Override
         public String toString()
         {
-            return String.format("%s %s (%s, %s), cds=%s, exon=%s", coordinate, name, start, end, cds, exon);
+            return ObjectLens.toJSON(this);
         }
     }
 
+    public static class BEDTrack
+    {
+        public String name;
+        public String description;
+        public String itemRgb;
+        public int visibility;
+        public String color;
+        public int useScore;
+        public String url;
+    }
+
     public static class BEDQuery
     {
         private String coordinate;
         private Locus queryRange;
-
         private List<BEDGene> geneList = new ArrayList<BEDGene>();
 
+        public BEDTrack track;
+
         public BEDQuery(String coordinate, long startOnGenome, long endOnGenome)
         {
             this.coordinate = coordinate;
index e3e4ba6..4bdbfcb 100644 (file)
@@ -73,4 +73,14 @@ public class ObjectLensTest
 
     }
 
+    @Test
+    public void canonicalNameTest() throws Exception
+    {
+        assertEquals("itemrgb", ObjectLens.getCanonicalParameterName("itemRgb"));
+        assertEquals("itemref", ObjectLens.getCanonicalParameterName("item_ref"));
+        assertEquals("helloworld", ObjectLens.getCanonicalParameterName("Hello World"));
+        assertEquals("helloworld", ObjectLens.getCanonicalParameterName("Hello-World"));
+
+    }
+
 }
index 949cfb9..b506183 100644 (file)
@@ -2,15 +2,15 @@
 \r
 -track(name:"Item,RGB,Demo2", description:"Item RGBdemonstration2", visibility:2, itemRgb:"On", useScore:1, color:"0,128,0", url:"http://genome.ucsc.edu/goldenPath/help/clones.html#$$")\r
  -gene(coordinate, start, end, name, strand, cds(start, end), exon(start, end)*, color, _[json])|\r
-chr7   127471197       127472364       Pos1    +       [127471197, 127472364]          #ff0000 {"score":300}\r
-chr7   127472364       127473531       Pos2    +       [127472364, 127473531]          #ff0000 {"score":200}\r
-chr7   127473531       127474698       Pos3    +       [127473531, 127474698]          #ff0000 {"score":900}\r
-chr7   127474698       127475865       Pos4    +       [127474698, 127475865]          #ff0000 {"score":400}\r
-chr7   127475865       127477032       Neg1    -       [127475865, 127477032]          #0000ff {"score":100}\r
-chr7   127477032       127478199       Neg2    -       [127477032, 127478199]          #0000ff {"score":500}\r
-chr7   127478199       127479366       Neg3    -       [127478199, 127479366]          #0000ff {"score":200}\r
-chr7   127479366       127480533       Pos5    +       [127479366, 127480533]          #ff0000 {"score":200}\r
-chr7   127480533       127481700       Neg4    -       [127480533, 127481700]          #0000ff {"score":600}\r
+chr7   127471197       127472364       Pos1    +       [127471197, 127472364]          "#ff0000"       {"score":300}\r
+chr7   127472364       127473531       Pos2    +       [127472364, 127473531]          "#ff0000"       {"score":200}\r
+chr7   127473531       127474698       Pos3    +       [127473531, 127474698]          "#ff0000"       {"score":900}\r
+chr7   127474698       127475865       Pos4    +       [127474698, 127475865]          "#ff0000"       {"score":400}\r
+chr7   127475865       127477032       Neg1    -       [127475865, 127477032]          "#0000ff"       {"score":100}\r
+chr7   127477032       127478199       Neg2    -       [127477032, 127478199]          "#0000ff"       {"score":500}\r
+chr7   127478199       127479366       Neg3    -       [127478199, 127479366]          "#0000ff"       {"score":200}\r
+chr7   127479366       127480533       Pos5    +       [127479366, 127480533]          "#ff0000"       {"score":200}\r
+chr7   127480533       127481700       Neg4    -       [127480533, 127481700]          "#0000ff"       {"score":600}\r
 chr22  2001    7001    itemB   -       [2201, 6951]    [[1, 433], [501, 600], [2001, 2550], [3501, 5000]]              {"score":200}\r
 chr22  2001    6001    cloneB  -       [2001, 6001]    [[1, 433], [3602, 4000]]                {"score":900}\r
 chr22  1001    5001    itemA   +       [1101, 4701]    [[1, 1567], [2513, 4000]]               {"score":960}\r
@@ -24,4 +24,4 @@ chr22 20100401        20100501        thirds
 chr7   127472364       127473531       Pos2                                    {"score":200}\r
 chr7   127472364       127473531       Pos2    +                               {"score":200}\r
 chr7   127472364       127473531       Pos2    +       [127472364, 127473531]                  {"score":200}\r
-chr7   127472364       127473531       Pos2    +       [127472364, 127473531]          #ff0000 {"score":200}
\ No newline at end of file
+chr7   127472364       127473531       Pos2    +       [127472364, 127473531]          "#ff0000"       {"score":200}
\ No newline at end of file