Matlab Utilities
Usage Information
All of the Matlab tools described here, along with their supporting JAR files, are distributed with both Figure Composer and DataNav Builder. Note that you must have Matlab 7.x or later to use these functions. For full details on how to use each function, make sure the requisite M-file is in your Matlab command path, then type help function-name at the command prompt. We strongly recommend that you read the help information carefully.
The supporting JAR files must be in Matlab's Java class path or these functions will not work; instead, you will see some mysterious error messages in the command console when you try to execute a function. To add the JAR files to the dynamic class path, use the Matlab command javaclasspath({'jarpath1', 'jarpath2', ...}), where 'jarpath1', 'jarpath2', ... are full file system pathnames identifying the required JAR files. Of course, you have to remember to execute this command each time you start Matlab. A more convenient approach is to use the javaaddpath command in your startup.m file: javaaddpath jarpath1, javaaddpath jarpath2, ...
Convert a Matlab figure to a DataNav figure: matfig2fyp()
Perhaps the most difficult obstacle to composing scientific figures in DataNav is getting the actual raw data into the application in a manner that is convenient for users. Our first attempt to address this roadblock was the utility function putdatanavsrc(), which lets the Matlab user populate a file with any number of DataNav-formatted data sets. Then, in DataNav itself, the user can design the figure from scratch and load the necessary data from that file. However, this strategy requires a certain familiarity with the different data set formats supported by DataNav, learning how to use the relatively complex putdatanavsrc() function, and then the additional work of creating a figure from scratch in DataNav and loading data into it.
Since so many researchers in neuroscience (and other areas of study) are accustomed to analyzing their data and preparing figures in Matlab, it would be extremely helpful if a Matlab figure could be translated directly -- data and all -- into a DataNav FypML figure. That is exactly what matfig2fyp(H, F) does. It takes the handle H of an open Matlab figure, converts it to an equivalent DataNav figure, and saves it to the file F. This file can then be opened in Figure Composer, and the figure modified and embellished as needed to prepare it for scientific publication.
Of course, many Matlab figures cannot be converted because DataNav does not support all the features and specialized plotting functions that Matlab offers. Nevertheless, in its current state, the function can convert a Matlab surface or image object to a DataNav contour node (in the "heatMap" display mode); it can generate trace nodes rendering ptset, series, mset, or mseries data from Matlab line series plots; it can convert specialized 2D plots generated by Matlab's polar(), rose(), compass(), bar(), area(), pie(), scatter(), contour(), and contourf() functions; and it can convert raster train plots generated by the dn_rasterplot() function, described below. As of Version 5.0.0, it can translate most 3D plots generated by Matlab's surf(), scatter3(), and stem3() functions. It translates each Matlab axes in the figure into a DataNav graph node -- or graph3d node for 3D plots --, preserving the axis ranges, labels, and major tick marks if possible, and it will replicate any legends and color bars present in the figure. We will continue to enhance its capabilities as users provide feedback.
Save a Matlab FIG file to be imported by DataNav: savefigasis()
As of Version 4.2.3, Figure Composer and DataNav Builder can import a Matlab figure saved as a MAT file with the .fig extension. The conversion code is the same as that used by the matfig2fyp() utility. However, there are two issues with the direct import feature:
Newer versions of Matlab may be configured to save the FIG file in the HDF storage format, which the DataNav applications are unable to read at this time. You can set your Matlab preferences to use the older "-v7" storage format, or you can specify that format when you save a particular figure.
When a Matlab figure is saved to a FIG file, the axis ranges and tick marks for a Handle Graphics "axes" or "scribe.colorbar" object may not be saved. When such a FIG file is opened in DataNav, the import engine configures the corresponding FypML "graph" or "color axis" to be auto-ranged. Generally, this means that the graph will likely have somewhat different axis ranges and tick mark sets compared to the original Matlab figure.
The savefigasis() utility is provided to help you skirt these two issues. It's essentially a wrapper for the Matlab built-in function hgsave(). It calls that function with the "-v7" argument to ensure the FIG file is saved in the storage format (MAT Level 5 with compression) that Figure Composer can handle. In addition, it sets select properties on all "axes" and "scribe.colorbar" objects to ensure that the exact axis ranges and tick mark sets are explicitly stored in the FIG file. We recommend using it to save any Matlab FIG file you plan to import directly into FC.
Inject a data set, text, or a graph into a FypML figure: put2fyp(), putdata2fyp()
Suppose you have a complete, nicely formatted figure in Figure Composer. It's ready for publication, but then you get comments back from reviewers that prompt you to revise your analysis somewhat. Now you need to replace several of the data sets in your figure, and you'd like to do that without having to rebuild the figure from scratch. This is where the Matlab utility function put2fyp(F, 'data', ID, X, Y, ...) may come in handy. It lets you inject a data set prepared in Matlab directly into an existing FypML figure without changing how that data is rendered. You can either overwrite the existing FypML file (the F argument) or save the updated figure to a different file.
The utility replaces the little-used and now-deprecated putdatatofig() function. Unlike that function, put2fyp() shields the user from the nitty-gritty details of the various FypML-supported data formats. The data to be injected is specified only by an x-coordinate vector and a y-coordinate vector or matrix, a natural way for Matlab users to present or prepare 2D data sets. The function examines the X,Y arguments and the data set being replaced (identified by the ID argument) in order to infer what the format and parameters of the new data set should be. Best of all, you can optionally preview the revised figure before saving it, which can save you time if you make a mistake in the script that generates the data. You no longer have to save the figure, open it in Figure Composer, discover your mistake, and then go back to Matlab to fix it! To make it simpler to use, put2fyp() only lets you inject one data set at a time into a figure. This should not be a significant limitation -- just invoke the function once for each data set you need to replace.
To use put2fyp() effectively, you need to know the character string identifier (the ID argument) of each raw data set you want to replace in your figure. This remains a barrier to the function's adoption for many users, who tend not to assign "memorable" set IDs to the data sets in their figures. Also, to specify less-intuitive data sets like raster-type data or data points with x- and/or y-standard deviations, you'll still have to dive into the detailed information provided in the Matlab command window by help put2fyp.
The put2fyp() utility is actually an enhanced version of the older putdata2fyp(). In addition to injecting raw data, the utility also lets you make other changes to an existing figure:
put2fyp(F, 'note', S) lets you set or update the note property of the root figure node. The figure note is for informational purposes only. It does appear in the figure preview in FC's file chooser dialog and workspace browser.
put2fyp(F, 'text', ID, S) or put2fyp(F, 'title', ID, S) lets you replace the text content of a label or textbox node, change the title of a graph node, or change the title of any data presentation node (trace, raster, heatmap, bar, scatter). [You can use either operation code -- 'text' or 'title'; they're essentially synonymous.] The string argument ID identifies the graphic object to be modified, and S is the replacement text. The location and styling of the object are unaffected. If you need to specify where the line breaks occur for text in a text box, the argument S should be a cell array of strings instead of a single character string. For all other nodes, the replacement text will be a single-line string (even if S is a cell array). Note that a graph, label, or textbox object is uniquely identified by assigning it an object ID (the id attribute introduced in version 4.6.2). For data presentation nodes, ID refers to the string identifier for the node's source data set. In rare cases, multiple data presentation nodes in a figure could share the same data set; in this scenario, the command would update the title of all such nodes.
put2fyp(F, 'legend', ID, POS, LBL) lets you change the legend label for any data group in a bar, area or pie chart. [These three types of data presentation nodes present groups of data, with a separate legend entry for each such group.] The string argument ID identifies the source data set of the affected data presentation node, POS is the index position of the data group to be updated (an integer), and LBL is its new legend label (a single-line character string). Again, in the unlikely event that multiple presentation nodes share the same data set, all of those nodes will be updated in the same manner.
put2fyp(F, 'graph', ID, H) replaces an entire graph in your figure. Again, ID identifies the graph to be replaced, while H is the handle of a Matlab 'axes' object currently on display in the Matlab environment. This 'axes' defines the replacement graph. The original graph can be 2D or 3D; same for the replacement graph. Typically, both graphs will be 2D or both 3D, but that is not a requirement. Note that the location, dimensions, and overall style of the original graph is preserved -- in an effort to make the replacement graph "fit in" with the rest of the figure. [However, if the original graph is 2D and its replacement is 3D -- or vice versa --, you will definitely need to make some changes in the resulting figure. The location and dimensions of a 2D graph have a very different interpretation versus a 3D graph.
These commands became possible with FypML schema changes in versions 4.6.2 and 4.7.0, particularly the introduction of the id attribute for graph, label, textbox nodes. This attribute is similar to the data set ID mentioned above, except that it is optional (typically, you'll "ID" only those graphic objects that you might want to change via script) and can contain any Unicode character supported in FC.
As of version 4.7.3, two additional operations give you some control over layout of the graphs within a FypML figure:
put2fyp(F, 'figure', L) creates an empty figure and saves it in the FypML file F. L = [x y w h] indicates the location and size of the figure on the printed page.
put2fyp(F, 'addgraph', H, L) converts an 'axes' object in an open Matlab figure to a FypML graph or graph3d node, which is then inserted into an existing FypML figure defined in file F. H is the handle of the axes object, and L specifies the location and dimensions of the graph in inches. For a 2D graph, L = [x y w h], where (x, y) are the coordinates of the bottom-left corner of the graph's "data window" with respect to the bottom-left corner of the parent figure, and (w,h) are its width and height. For a 3D graph, L = [x y w h d], where (x,y) are the coordinates of the 3D coordinate system's origin WRT the parent figure, and (w, h, d) are its X-axis, Y-axis, and Z-axis extents in 3D space.
When using the 'addgraph' operation to layout 2D graphs in a multi-plot figure, keep in mind that the argument L defines the bounding box for the graph's data window, and the graph's axes are typically drawn outside that window. The amount of space occupied by an axis will depend on a number of graph properties (axis label offset, axis offset from data window, tick mark size, font size). In the 3D case, the graph will be roughly centered around (x,y), but its actual size depends on its backdrop style, the values of (w,h,d), and the graph's rotation and elevation angles. It is reasonable to expect that you will have to "tweak" the locations and sizes of graphs within a multi-plot figure created via put2fyp().
[NOTE: While put2fyp() is intended to replace putdata2fyp(), the latter function is still distributed with FC so that existing user scripts need not be changed. However, putdata2fyp() is considered "obsolete" and will be removed in a future release.]
Create a "raster train" plot in Matlab: dn_rasterplot()
A common figure in neuroscience circles is the "raster plot", which presents spike occurrence times as a series of short vertical lines along a common baseline parallel to the X-axis. Typically, a number of these "raster trains" are presented in the same graph, spaced vertically as in the example below:
Compatibility with Matlab R2014b
Matlab release 2014b (R2014b) introduced a major overhaul in its figure graphics, including significant changes in its Handle Graphics (HG) object infrastructure. Both the matfig2fyp() utility and Figure Composer's FIG file import engine must analyze the HG tree structure in order to prepare a Java version of that tree that contains enough information to translate the original Matlab figure into a FypML figure. Some of the graphics changes in R2014b created compatibility issues with FC's import code.
Version 4.6.2 addressed these issues, so you should now be able to run matfig2fyp() in R2014b and import FIG files generated by that release. (Unsupported features and plots will still fail to import, of course). This version also adds a new color map that is somewhat like Matlab's new default color map, so figures relying on that color map should look similar when converted by matfig2fyp() or imported directly into FC.
Feel free to upgrade your Matlab installation to R2014b. If you run into any problems using matfig2fyp() in that release, or you are unable to import a FIG file generated by R2014b, send us the FIG file along with an explanation of what went wrong. Thanks!
Since Matlab does not offer a plotting function for this kind of presentation of 1D discrete-time event data, we developed a utility function that does: dn_rasterplot(R, ...). It prepares a specialized polyline that draws a single vertical hash mark for each event in R, using (NaN, NaN) for every third point in the polyline so that the hash marks are not connected to each other. The argument R can take two forms:
An NxM matrix. Each column represents a separate raster train, while the rows represent time elapsed. A nonzero value in R(n,m) indicates that an "event occurred" at time (n-1) in the m-th raster train.
An Mx1 cell array of vectors. Each vector contains the event occurrence times for the m-th raster train.
For a complete description of the function and its other arguments, download dn_rasterplot.m, install it in your Matlab command path, and type help dn_rasterplot on the command line.
NOTE that a Matlab figure containing raster trains generated with dn_rasterplot() can be translated into a similar DataNav figure using matfig2fyp(). Each raster train will be presented in a raster node, and the actual event data will be drawn from the polyline's X- and Y-vectors and stored in the DataNav figure as a data set in raster1d format. In fact, the graph above is an image of a DataNav figure prepared by using dn_rasterplot() to create the Matlab figure, then matfig2fyp() to convert it to DataNav FypML format.
Read/write DataNav data set source files in Matlab: getdatanavsrc(), putdatanavsrc()
While the Dataset Editor Dialog is reasonably easy to use and flexibly supports cut-and-paste from applications like Excel, it remains a relatively laborious and time-consuming method for pushing data into a DataNav figure. It is really intended more as an avenue for viewing and editing the raw data, or for creating very small data sets from scratch. Furthermore, it would be impractical as a means of entering data into a DataNav portal, since a portal hub will typically contains hundreds, if not thousands, of data sets. What is needed is an automated means of storing one or more data sets in a source file that can then be read by the DataNav applications.
Data set source files in Phyplot -- the predecessor to DataNav's Figure Composer -- were plain-text files containing columns of floating-point numbers with little or no "metadata" describing the data (ID, format type, parameters like the sample interval dx). A blank line in the file separated one data set from the next. The advantage of such a simple format was that it was easy for any user -- regardless what tools they used to generate their data -- to repackage it in a form that Phyplot could handle.
However, this simple format has a number of serious disadvantages that make it ill-suited for use in the DataNav apps:
It is very inefficient. Storing a single-precision floating-point value always requires 4 bytes in a binary file, possibly fewer if compression is used. In a plain-text file, the number of bytes can be as little as 2 (e.g., "0" plus a delimiter character), but will typically be much larger than 4 (e.g., "-100.68" takes 8 bytes, 7 characters plus the delimiter). If the source file will contain many large data sets, a binary format is a much better solution.
It does not support randomly accessing a selected data set within the file. Since DataNav Builder must work with large repositories of data, it makes little sense to store each data set in a separate file - a lot of little files wreaks havoc on the file system! The better solution is to put a whole bunch of data sets (typically, related in some way) in a single file. In addition, authors using Figure Composer to prepare the figures for a journal paper can benefit from being able to store all the figure data in a single file. This introduces a new problem -- extracting a single data set from such a file. With the old Phyplot numbers-only format, this was impossible because there was no identifying information (except order within the file). Even with the simple annotated format, we would still have to read the file line-by-line until we found the right data set.
DataNav addresses these problems by supporting a binary data source file format with a table of contents at the beginning of the file that includes summary information and file offsets for each data set stored in the file. In addition, it supports an annotated plain-text format with a table of contents. This format is less compact than the binary format, but it is better suited for transmission over the Internet. The recommended (but not required, since each format includes a header for identification purposes) file extension for the binary format is .dnr (formerly, .dnb); for the annotated format, .dna or .txt.
Of course, introducing an opaque "proprietary" format means we need to provide tools for reading and writing these files. Since members of the Lisberger laboratory use Matlab extensively to analyze their data, we developed the complementary Matlab M-functions, putdatanavsrc() and getdatanavsrc(). Use putdatanavsrc() to write Matlab-generated data in DataNav-compatible data source files in either format -- although you are encouraged to use the binary format exclusively unless you have a really good reason not to do so! With it you can store any number of data sets in a single file, as long as each data set has a unique identifier. Use getdatanavsrc() to read datasets from a DataNav data source file back into Matlab. The source file may have been generated by a DataNav application, by the Lisberger lab's analysis program JMWork, or by a previous call to putdatanavsrc().