Motivation

The goals of this major revision of CX are

  1. Making the CX data model simpler so that it can be easily understood and used by developers.
  2. Better support for processing networks while streaming. The 2.0 spec will significantly reduce the memory footprint for operations such as filtering nodes and edges based on node/edge properties and converting the CX network to other formats.
  3. Making CX networks more compact to improve data transfer speed.

NOTE: CX version 2 is commonly referred to as CX2. In the Cytoscape ecosystem, CX2 files are typically denoted with the .cx2 extension, distinguishing them from CX version 1 networks, which are usually represented with the .cx suffix.

Table of contents

  1. Top Level Structure of CX
  2. CX Descriptor
  3. Pre and Post Metadata in CX
  4. Aspect Data Blocks
  5. Status Aspect
  6. CX Core Aspects
  7. Opaque aspects
  8. Numeric values in this version of CX
  9. Example CX files

Top Level Structure of CX

At the top level, a CX network is represented as a JSON array of objects which has this structure

[
  <CX descriptor>,
  <Optional pre-metadata>,
  <aspect data block 1>,
  <aspect data block 2>,
  ...
  <aspect data block N>,
  <Optional post-metadata>,
  <status Aspect>
]

CX Descriptor

A CX document always starts with this object. It defines some global attributes in this object. It has these attributes in it

  { 
    "CXVersion": 	string
    "hasFragments":	boolean
  }
  • “CXVersion” - the version number of the CX schema used in this document. Its format is “major.minor”. Required
  • “hasFragments” - indicate if the data in any aspect are broken into multiple fragments in this CX document. The default value of this attribute is false, which means each aspect only appears once in the CX document.
    • Allowing fragmented aspects can be useful in applications that need to incrementally write out mixed types of elements when generating a CX network. One common use case is that an application needs to stream out a subnetwork from a large network when traversing the large network.
    • Non-fragmented CX networks are more compact and will allow users to write more efficient applications. For example, if an application only needs a certain aspect when reading a non-fragmented CX network from an input stream, the application can stop the reading when it sees the end of that aspect.

Pre and Post Metadata in CX

CX aspect metadata declaration is optional. It can be used for data integrity checks when users want to use a CX document. Aspect metadata can be declared in either pre or post metadata sections. A network creator should always put metadata in the pre-metadata section if it is possible.

A metadata object has these attributes in it:

  {
    "name":         string,
    "elementCount": long 
  }
  • “name” - the name of the aspect and is the only required attribute.
  • “elementCount” - the number of elements in this aspect. It is optional.

Aspect Data Blocks

Aspect data blocks contain network data that are organized in aspects. When the aspect data blocks are completely missing, this CX document represents an empty network.

Each data block is a JSON object that has a single attribute in it. The name of the attribute is the aspect name. Its value is a list of aspect elements. All elements in an aspect should have the same data structure. The format of an aspect data block is like this:

{ ASPECT_NAME: [ aspect_elements ] }

Status Aspect

A complete CX stream ends with a status aspect. This aspect tells the recipient if the CX is successfully generated by the source. A use case is that a source is generating a CX network incrementally and transmits the data to the recipient through a stream, when an error occurs during the creation of the CX network, the source can write out a status aspect to the CX stream with some error message in it and finish the CX network immediately. The recipient will know from this aspect that the CX is a bad object and can stop the downstream process on this network. The status aspect has this structure:

{
  "status" : [ {
    "error" : string,
    "success" : boolean
   } ]
}

The "error" field holds the error message when an error occurs. "success" fields tell if the CX document is successfully generated by the source. If the value of "success" is true, value in attribute "error" will be treated as a warning.

CX Core Aspects

Core aspects are the set of aspects that are supported by all Cytoscape Ecosystem compatible applications. These are the names and definition of core aspects in CX

attributeDeclarations

This aspect is for declaring the data type, default value, or alias of attributes.

For a given attribute in an aspect, its type has to be declared before it appears in an aspect element. All values of an attribute must have the same data type in an aspect.

This aspect can be fragmented, but when an attribute type is declared, it has to be declared before it is used in that aspect.

The schema of this aspect is:

{
  Aspect_Name1: { attribute1: {"d": string, "a": string},
                  attribute2: {"d": string},
                  …
                  attributeN: {"d": string}    } ,
  Aspect_Name2: { attribute1: {"d": string, "v": value}, … },
   … 
}
  • Aspect_Name - The name of the aspect that this attribute is in. It can be networkAttributes, nodes, edges, edgeAttributes, or nodeAttributes. edgeAttributes and nodeAttributes aspects are only for Cytoscape collections.
  • attributeN - The name of the attribute in that aspect.
  • “d” - Declares the data type of that attribute. CX supports these data types in attributes:
    • string
    • long
    • integer
    • double
    • boolean
    • list_of_string
    • list_of_long
    • list_of_integer
    • list_of_double
    • list_of_boolean
  • “v” - Declare a default value for that attribute. This field (and also the next field “a”) is ONLY supported in the nodes or edges aspects. If “v” is defined for an attribute in an aspect, when an element doesn’t have that attribute in it, an attribute with the default value will be created in that element. Using this declaration can reduce the size of a CX document when one attribute value is repeated many times in an aspect. Developers need to be careful when using this field. This field can only be used when there is no null value on that attribute. For the same network, different developers or applications might choose a different value as the default value for a given attribute.
  • “a” - Use an alias to shorten attribute names, mainly for nodes and edges aspect. Network attribute aliases are NOT allowed. An alias should be unique in that aspect and should be different from any un-declared attribute in that aspect. If an alias is declared for an attribute, the full attribute name can no longer be used in that aspect.

networkAttributes

For a single network, the networkAttributes aspect has only one element. This element is a JSON object with these reserved attribute names:

  • name - title of the network
  • description - a brief description of the network
  • version - version of the network

nodes

{
  "id":  long,
  "v":   object
  "x":   double,
  "y":  double,
  "z" :  double,
}
  • “id” - the unique id in the scope of the nodes aspect.
  • “v” - holds all node attributes as one JSON object. In this object, attributes “x”,”y” and “z” are treated as ordinary attributes instead of coordinates. To avoid confusion, the attribute name “id” is not allowed in this object. Also, there are 3 reserved node attribute names in CX:
    • “name”: node name. Is normally used as a label for the node when the network is visualized as a graph. For biological networks, we recommend using gene symbols as node names (if possible) to increase the interoperability of your network with other applications in the Cytoscape ecosystem. Its type is string.
    • “represents”: a standard identifier defining what the node represents. Its type is string.
    • “alias”: alternative identifiers for the node. Its type is list-of-string.
  • “x” - the x coordinate of the node.
  • “y” - the y coordinate of the node. x and y attributes are optional, but CX has these constraints on them If a node has an “x” value in it, it must also have a “y” value. If one node has an “x” and “y” value, all nodes in this CX network must have x and y values.
  • “z” - z coordinate or z-order, depending on how the renderer interprets it. This property is optional. If a node has a ‘z’ attribute, it must also have x, and y. If one node has a ‘z’ coordinate, all nodes should have “z” attributes.

The coordinates in this aspect are only for single networks. Node coordinates in Cytoscape Collections are stored in the cartesianLayout aspect because they are associated with a view.

edges

{
  "id": long,
  "s" : long,
  "t" : long, 
  "v" : object
}	
  • “id” - is the unique id of the edge in the scope of this aspect. Required
  • ”s” - id of the source node. Required.
  • “t” - id of the target node. Required.
  • “v” - holds all attributes on this edge as a JSON object. Like the “v” attribute in nodes, this object doesn’t allow the attribute “id” in it. It also treats “s” and “t” as normal attributes in it.

visualProperties

This aspect defines the default visuals styles and data-driven mappings in this network. There is only one element in this aspect. This aspect should not be fragmented.

The graphic properties in this aspect only support Cytoscape Portable Graphic Styles. If a user wants to store non-portable visual styles such as native Cytoscape desktop application specific visual properties, they can be stored in an opaque aspect such as cyVisualProperties. It is recommended to put all portable visual properties and styles in the visualProperties aspect so that they can be supported by a broad range of tools in the Cytoscape ecosystem.

The data type of visual attribute values is predefined either by Cytoscape or the portable visual style standard.

Elements in this aspect has this structure:

{
  "default": {
	"network": {
        attribute_1: value,
        attribute_2: value,
           ...
      },
     "node": {
        attribute_1: value,
        attribute_2: value,
          ...
    },
    "edge": {
        attribute_1: value,
        attribute_2: value,
         ... 
    }
   },
  "nodeMapping":{
      Attribute_1: {
        "type":  "DISCRETE" | "PASSTHROUGH" | "CONTINUOUS",  
        "definition": <mapping serialized to JSON>},
      Attribute_2: {
        "type": value
        "definition": <<mapping serialized to JSON>},
      ...        
  }
  "edgeMapping":{
     ...
  }
}

Each type of mapping has a specific schema. The schema for the PASSTHROUGH mapping is:

  {
    "attribute": string,
    "type": string 
  } 
  • “attribute” - attribute name. This is the original attribute name as is used in node or edge attributes, or the expanded name defined in the attributeDefinitions aspect. NOTE: A shortened attribute name (alias) cannot be used here.
  • “type” - data type of that attribute. The data type of this attribute is required only when it is not defined in the attributeDeclarations aspect. In cases where the attribute is declared in the attribute declaration, its data type is inferred from the attribute name.

Schema for DISCRETE mapping is

{
  "attribute": string,
  "type": string,
  "map": [{ "v" : data_value, 
            "vp": visual_property_value }]  
}	

The data types for ‘data_value’ and ‘visual_property_value’ can either be specified by the ‘type’ attribute or inferred from the names of the corresponding attributes and visual properties

Schema for CONTINUOUS mapping is

{
  "attribute": string,
  "type": string,
  "map": [{
             "min":       double,
             "includeMin": true | false,
             "max":       double,
             "includeMax": true | false,
             "minVPValue": visual_property_value,
             "maxVPValue": visual_property_value
          }]  
}	

nodeBypasses

This aspect stores all the bypass visual properties on nodes. Its element has this data structure

{
   "id": long,
   "v":  Object
}
  • “id” - is the node id.
  • “v” - is an object that stores visual properties. The values are simple objects with name-value pairs in it. The attribute name is the visual property name. This is an example element in this aspect:
{ 
  "id": 245,
  "v" : {
        "NODE_BACKGROUND_COLOR": "#89D0F5"
        "NODE_SHAPE":   "round-rectangle"
     }
}

edgeBypasses

Similar to the nodeBypasses aspect, this aspect stores all the bypass visual properties on edges. The data structure of its element is

{
   "id": long,
   "v": Object
}
  • “id” - is the edge id.
  • “v” - is an object that stores visual properties. The values are simple objects with name-value pairs in it. The attribute name is the visual property name. This is an example element in this aspect:
{ 
  "id": 245,
  "v": {
      "EDGE_BEND": [
           0.8534737565017845, 
           0.5211358239103628, 
           0.6999978351246443
         ],
      "EDGE_WIDTH": 5
    }
}

visualEditorProperties

This aspect determines the default visual styles for displaying the network in applications with editing capabilities. Currently, it’s utilized in both the Cytoscape desktop and web applications. This aspect should contain only one element. This singular element is an object endowed with the following attributes:

  • arrowColorMatchesEdge - If true then Color (Unselected) is used for the whole edge, including its line and arrows.
  • nodeSizeLocked - Lock node width and height when this value is set to true.
  • NETWORK_CENTER_X_LOCATION - The X location of network view center when opened. When opening a CX network in Cytoscape, Cytoscape will establish the the zoom level and the center of the network when NETWORK_CENTER_X_LOCATION, NETWORK_CENTER_Y_LOCATION and NETWORK_SCALE_FACTOR are all defined. Otherwise, when the nework is opened, Cytoscape will automatically fit the network within the viewport.
  • NETWORK_CENTER_Y_LOCATION - The Y location of network view center when it opened.
  • NETWORK_SCALE_FACTOR - The zoom level of the network view when opened.

Opaque aspects

Applications are allowed to add any non-core aspects to CX as extensions. These aspects are called ‘opaque aspects’. The element of an opaque aspect is a JSON object, and all elements in an opaque aspect should have the same data structure. Attributes in opaque aspect elements can also be declared in the attributeDeclarations aspect.

An opaque aspect is in this format in a CX document:

{
   Aspect_name: [
    Element1, 
    Element2,
	...
   ]
}

Numeric values in this version of CX

CX supports these 3 numeric data types:

  • long
  • integer
  • double

A CX network is a JSON document that follows the JSON specification. However, the JSON specification only includes a generic number type, which can lead to imprecision in numeric data types for node and edge attribute values. To ensure precision, it is necessary to use the attribute declaration aspect to cast the CX2 numeric values to their declared data type. Note that the double data type has special values like NaN, -Infinity, and Infinity, which are not supported in the JSON specification. Consequently, when converting a CX network into CX2, NDEx server will convert these values to nulls. If your application requires the preservation of NaNs, you can save the corresponding column as a string and handle the string-to-double conversion in your application.

Example CX files

Example 1