iSpy Client

View the Project on GitHub cms-outreach/ispy

What is this?

iSpy is a powerful and lightweight event display used for the CMS experiment at the LHC. It reads in an ig file which contains event and geometry information.

Example display

What is an ig file?

A .ig file is a zip archive (unzippable via unzip or similar) containing one file per event. Each event file uses a relational database-like structure, described using JSON.

ig-file format:

ig files have a flat directory structure with a separate directory per run (run directory). Each run directory contains one or more files describing a given event (ig event file) each. The associated run number and the event number are, respectively, the file name for the run directory and for the ig event file.

The ig-event-file format is a valid JSON or python dictionary. The format defines three categories of objects: types, collections and associations-sets.


ig-event-file ::= { 'Types': type-descriptions, 'Collections': collections, 'Associations': association-sets }


Types are a mapping of a type-name and its associated type-description. The type-description defines the types of the objects that are to be found in the Collection which uses the same string as the type-name to be identified. The attributes (i.e. columns) of a Collection are defined by an attribute name and an attribute type. The former is just a string label, while the second one define the kind of object which is stored in the attribute, all of which have a C++ equivalent. Possible attribute types include:


type-descriptions ::= { type-description, ... }

type-description ::= "type-name": [attributes-description, ...]

type-name ::= string-literal

attribute-description ::= ["attribute-name", "attribute-type"]

attribute-name ::= string-literal

string-literal ::= [A-Za-z_][A-Za-z_/0-9]*

attribute-type ::= int OR long OR double OR string OR v2d OR v3d OR v4d


Collections are arrays of rows, identified by a collection-name. The collection-name is a string-literal which matches one of the type-names defined in types. Rows are arrays of values, where the type of the value matches the attribute-type of the attribute-description with the same position in the type-description which has its type-name matching the collection name.

This is the actual data contained in a file.


collections ::= {collection, ... }

collection ::= "type-name": [row, ...]

row ::= [ value, ...]

value ::= string-literal OR numeric-literal OR vector-literal

numeric-literal ::= [0-9]+[.][0-9]

vector-literal ::= [numeric-literal, numeric-literal, ...]

Association sets

An association defines a relationship between two rows found in any (possibly the same) collections. They are uniquely identified by two couples of numbers, the first one uniquely identifying the left object of the association, the other identifying the right object. The first element of this couple of numbers is the so called collection id while the second one is called object id. The collection id is the index of the collection type within the Types table, while the object id is the index of the object within the collection. Such a couple of numbers is called object reference. An association-set is an array of associations which share some common meaning decided by the writer of the ig-file.


associations-sets ::= { association-set, ... }

association-set ::= "association-set-name": [association, ...]

association ::= [left-object, right-object]

left-object ::= object-reference

right-object ::= object-reference

object-reference ::= [collection-id, object-id]

collection-id ::= index-literal

object-id ::= index-literal

index-literal ::= [0-9]+


Here is a simple example of what an ig file looks like.

 "Types": {"Tracks_V1": [["x", "double"],["y", "double"],["z", "double"],
                         ["px", "double"],["py","double"],["pz", "double"]],
           "Clusters_V1": [["x", "double"],["y", "double"],["z", "double"],
                           ["e", "double"]]
 "Collections": {"Tracks_V1": [[0, 0, 0, 0, 0, 0],
                               [1, 1, 1, 1, 1, 1],
                               [2, 2, 2, 2, 2, 2],
                               [3, 3, 3, 3, 3, 3],
                               [4, 4, 4, 4, 4, 4],
                               [5, 5, 5, 5, 5, 5],
                               [6, 6, 6, 6, 6, 6],
                               [7, 7, 7, 7, 7, 7],
                               [8, 8, 8, 8, 8, 8],
                               [9, 9, 9, 9, 9, 9]],
                 "Clusters_V1": [[0, 0, 0, 0],
                                 [1, 1, 1, 1],
                                 [2, 2, 2, 2],
                                 [3, 3, 3, 3],
                                 [4, 4, 4, 4],
                                 [5, 5, 5, 5],
                                 [6, 6, 6, 6],
                                 [7, 7, 7, 7],
                                 [8, 8, 8, 8],
                                 [9, 9, 9, 9]]
 "Associations": {"TrackClusters_V1": [[[0, 0], [1, 0]],
                                       [[0, 1], [1, 1]],
                                       [[0, 2], [1, 2]],
                                       [[0, 3], [1, 3]],
                                       [[0, 4], [1, 4]],
                                       [[0, 5], [1, 5]],
                                       [[0, 6], [1, 6]],
                                       [[0, 7], [1, 7]],
                                       [[0, 8], [1, 8]],
                                       [[0, 9], [1, 9]]],
                  "TrackClusters2_V1": [[[0, 0], [1, 0]],
                                        [[0, 1], [1, 0]],
                                        [[0, 2], [1, 0]],
                                        [[0, 3], [1, 0]],
                                        [[0, 4], [1, 0]],
                                        [[0, 5], [1, 0]],
                                        [[0, 6], [1, 0]],
                                        [[0, 7], [1, 0]],
                                        [[0, 8], [1, 0]],
                                        [[0, 9], [1, 0]]]


APIs for ig files can be found on github:

How do I make my own ig files?

See an example here.

How do build it?

iSpy uses among other libraries Qt, Coin3D, and SoQt. The relative simplicity of your build (which uses cmake) may vary. That said, in order to give it a try:

git clone
cd ispy
git checkout linux64 (or git checkout mavericks)
cd externals
cmake .
cd ../
cmake .

How do I run it?

Once downloaded (or built), iSpy should be a full-bound executable. You can double-click it or run it from the command line (you may need to chmod +x). Some files are provided via the www. You can read local files from the File menu or specify them on the command line as an argument.

Alternatively, you can try the browser-based version (written in JavaScript) either offline or online.

How do I change the colors/cuts, etc.?

iSpy uses so-called ISS files (mimicking HTML CSS files) that define the style and (graphics) cuts for any given collection displayed.

While a default ISS file is compiled in the executable, the user can specify his/her own file at startup time by simply passing its path on the command line.

The syntax of ISS is as similar as possible to the one of the usual CSS file encountered in web pages:

      rule {
        property-name: property-value;

Where rule is used to identify the collection name for the associated properties found in the curly brackets.

Notice that for the moment, due to limitations of the implementation, the rule is not really cascading and you have to fully specify all the properties related to a given collection. This will change in future.

To define the default style you can use the * rule and define values for all the supported properties. At the moment the default "*" rule is:

      // Default style.
      * {
        diffuse-color: rgb(0.7, 0.7, 0.7);
        transparency: 0.0;
        line-width: 1.0;
        line-pattern: 0xffff;
        font-size: 12;
        font-family: Arial;
        draw-style: solid;
        marker-shape: square;
        marker-size: normal;
        marker-style: filled;
        text-align: left;
        min-energy: 0.2;
        max-energy: 5.0;
        energy-scale: 1.0;
        left: 0.;
        top: 0.;

For a detailed description of all the properties see the list below.

Besides all the collections to be found in the ig file, there are two special collections you can configure as well: Background and Internal_Limits_V1. The former obviously controls the background color (via the diffuse-color attribute), while the latter corresponds to the overlay which displays the graphics cuts.

Properties reference

How do I change the view contents, the camera position, etc.?

In order to configure which view are to be shown and what to show in each view, iSpy uses a so-called IML file. Such a file is a normal xml file with the following structure:

       <?xml version="1.0" encoding='UTF-8'?>
       <camera position="-18.1, 8.6, 14.0" pointAt="0, 0, 0" scale="10.6" orthographic="true" rotating="true">
         <view label="Standard 3D View" specialised="true" autoplay="true">
           <collection label="Provenance/Event information"

The <layout/> tag is just the top-level container.

The <camera/> tag specifies where the default camera should be put for the contained views.

The <visibilityGroup/> tag specifies where the default camera should be put for the contained views.

The <view/> tag specifies properties of the a page view. It contains a set of <collection/>tags, as many as one per collection to be displayed.

As for ISS files, a default IML file is compiled in the application but the user can specify his own by passing it on the command line.

Attributes of the <camera/> tag

Attributes of the <view/> tag

Attributes of the <collection/> tag

List of draw operations


iSpy contributors

George Alverson, Giulio Eulisse, Thomas McCauley, Lucas Taylor.

Former contributors

Shahzad Muzaffar, Ianna Osborne, Lassi Tuura.



J.Phys.Conf.Ser. 396 (2012) 022002 (DOI: 10.1088/1742-6596/396/2/022002)