Code covered by the BSD License  

Highlights from
Attributed Plot Html

image thumbnail

Attributed Plot Html

by

 

This exchange file creates a clickable image map for a figure with links to multiple data sources.

AttributedPlotHtml(Dim2Data,ImageName,Crux)
function AttributedPlotHtml(Dim2Data,ImageName,Crux)

%DynamicPlotSource - Creates image, map and html page for attributed data.
%          html page consists of title, plot, and list of sources for each
%          data point on the plot
%
% Syntax:  AttributedPlotHtml(Dim2Data,ImageName,Crux)
%
% Required Inputs:
%    Dim2Data - Two-dimensional matrix with data to be plotted
%               column 1 - x-axis
%               column 2 - y-axis
%
% Optional Inputs:
%    ImageName - String - title to be used for final image and htmlfile
%    Crux - Object - contains properties that are used for attribution and
%                    style
%
%    Recommended Crux Properties:
%       Crux.blurbs - Array of strings with length equal to Dim2Data,
%                   - brief description of data source
%       Crux.links - Array of strings with length equal to Dim2Data,
%                  - link to source of form: "http://www.google.com/"
%       Crux.xlab - string with label for x-axis 
%       Crux.ylab - string with label for y-axis 
%       Crux.imagewidth - number - width of image in inches (rec:5)
%       Crux.imageheight - number - height of image in inches (rec:3)
%    Optional Crux Properties:
%       Crux.plottitle - string title for plot
%       Crux.title - string title for page
%       Crux.linksx - Array of strings with length equal to Dim2Data,
%                  - link to source of x data (if different than y)
%                  - of form: "http://www.google.com/"
%       Crux.slinkFormat - string for sprintf to represent y data magnitude
%                        - ex: '%0.0f' for '54' output from 54.367 input
%                        - ex: '%0.2f' for '54.36' output from 54.367 input
%       Crux.slinkxFormat - string for sprintf to represent x data magnitude
%       Crux.plotfun - anonymous function that defines plot
%                    - see     help function_handle      for use syntax
%                    - must have only two inputs, xdata and ydata
%              Example
%              Crux.plotfun = @(xx,yy) plot(xx,yy,'.','MarkerSize',13);
%
%
% Outputs:
%    1) generates png file of data plot with name: ImageName.png
%    2) generates html file with plot and attributions: ImageName.html
%    3) generates txt file with html code of image and map: ImageName.txt
%
% Example:
%    Dim2Data = [10 2004;
%                11 2005;
%                12 2006];
%    ImageName = 'AttributedData';
%    Crux -- Example properties for Crux are listed in the nargin<1 section
%            below
%
% Other m-files required: none
% Subfunctions: none
% MAT-files required: none
% Hardware: none
%
% OS & MatLab version control
% tested and developed on: Windows 7 & MatLab 2012b
%
% See also: OTHER_FUNCTION_NAME1,  OTHER_FUNCTION_NAME2

% Author: Emily Alden
% March 2013; Last revision: 05-March-2013

%------------- BEGIN CODE --------------

%% Check Input Data 
%  sanitize and fill in excluded optional elements
if nargin < 1
    Dim2Data = [2000 11;
        2001 13;
        2001.3 8;
        2005 5;
        2008.2 2];    
        Crux.xlab = 'Time [years]';
        Crux.ylab = 'Data [units]';
end

%Confirm Two-dimensional input
datasize = size(Dim2Data);
if length(datasize) ~= 2, 
    error('Choose 2D data set to plot.')
end
if sum(datasize==2)<1,
    error(['Two dimensions of data required. Your data matrix has size: ['...
        num2str(datasize) ']. One dimension should be 2.']); 
end
if datasize(2) ~=2, Dim2Data = Dim2Data';end

%detemine number of data points in source
lenData = size(Dim2Data,1);

%create an array of tags for mouseover reference
refs = cell(lenData,1);
for ii = 1:lenData
    if lenData>9
        %adds leading zeros as needed to distinguish ref1 from ref11
        order = floor(log(abs(lenData))./log(10));
        oformat = ['ref%0' num2str(order+1) 'd'];
        refs{ii} = sprintf(oformat,ii);
    else       
        refs{ii} = sprintf('ref%d',ii);
    end
end 


if nargin < 2
    ImageName = 'AttributedData';
end


% Crux - the source and formatting info for the attributed data plot
if nargin < 3
    Crux.title = 'Attributed Data';    
end

%CruxElect = fieldnames(Crux);
%% Input Audit - The Optional Crux Object
if ~isfield(Crux,'title')||~ischar(Crux.title)
    Crux.title = '';
end

if ~isfield(Crux,'blurbs')
    blurbs = cell(lenData,1);
    for ii = 1:lenData
        blurbs{ii} = sprintf('blurb%d  a brief detail about the data',ii);
    end
    Crux.blurbs = blurbs;
elseif length(Crux.blurbs) < lenData;
    disp 'Insufficient number of blurbs, using generic blurb#'   
    for ii = length(Crux.blurbs)+1:lenData
        Crux.blurbs{ii} = sprintf('blurb%d  a brief comment about the data point',ii);
    end
end

if ~isfield(Crux,'links')
    links = cell(lenData,1);
    for ii = 1:lenData
        links{ii} = sprintf('http://www.google.com/search?q=%d',ii);
    end
    Crux.links = links;
elseif length(Crux.links) < lenData;
    disp 'Insufficient number of links, using generic link'    
    for ii = length(Crux.links)+1:lenData
        Crux.links{ii} = sprintf('http://www.google.com/search?q=%d',ii);
    end
end

if ~isfield(Crux,'xlab')
    Crux.xlab = '';
end

if ~isfield(Crux,'ylab')
    Crux.ylab = '';
end

if ~isfield(Crux,'imagewidth')
    Crux.imagewidth = 5;
end

if Crux.imagewidth > 13
    disp 'are you sure you want your final picture to be more than 13" wide? Please input the width in inches'
end

if ~isfield(Crux,'imageheight')
    Crux.imageheight = 2;
end

if ~isfield(Crux,'plottitle')
    Crux.plottitle = '';
end

%format of x data links text
if ~isfield(Crux,'slinkFormat')
    Crux.slinkFormat = '%0.2f';
end

%format of y data links text
if ~isfield(Crux,'slinkxFormat')
    Crux.slinkxFormat = '%0.2f';
end


%plot function style, default is basic MatLab plot
% tests to make sure input exists, is a function, and has two input
% arguments (AttributedPlotHtml.m will only execute this function with two
% input arguments (both vectors):xdata and ydata.
if ~isfield(Crux,'plotfun')||~isa(Crux.plotfun,'function_handle')||nargin(Crux.plotfun)<2
    Crux.plotfun = @(xx,yy) plot(xx,yy,'.','MarkerSize',13);

    % Examples of other plot functions
    %    %% line plot
    %    Crux.plotfun = @(xx,yy) line(xx(:),yy(:),'Marker','.','MarkerSize',13);
    %    %% errorbar plot
    %    yyunc = 0.3.*ones(lenData,1);
    %    Crux.plotfun = @(xx,yy) errorbar(xx(:),yy(:),yyunc,'.');
end

%build the html link syntax
s1 = '<a href="';
s2 = '"  target="_blank">'; %opens link in new tab/window
%s2 = '">'; %To open link in same tab/window, uncomment here
s3 = '</a>';

htmllinks = cell(lenData,1);
    
for iMkLink = 1:lenData
    ylink = [s1 Crux.links{iMkLink} s2 sprintf(Crux.slinkFormat,Dim2Data(iMkLink,2)) s3];    
    if isfield(Crux,'linksx')
        % if there is an x source link,
        xlink = ['&nbsp&nbsp' s1 Crux.linksx{iMkLink} s2 sprintf(Crux.slinkxFormat,Dim2Data(iMkLink,1)) s3];
    else
        xlink = ['&nbsp&nbsp' sprintf(Crux.slinkxFormat,Dim2Data(iMkLink,1))];
    end
    htmllinks{iMkLink} =  ['(' xlink ' , ' ylink ' )'];
end



%% Plot Function   
%sets the font size of the plot labels
fontsz = 6;
%sets the click radius (in pixels) of the html imagemap
clickrad = 10;

fWidthIn = Crux.imagewidth;
fHeightIn = Crux.imageheight;
%300dpi is the ultimate, high resolution image, but we use 150dpi ratios
%for screen display during the execution of this code and to define the
%pixel size displayed in the final html page
resDPI = 300;
dispPix = 150;
fWidthPix = fWidthIn*dispPix;
fHeightPix = fHeightIn*dispPix;

h = figure(137);
clf;

units = 'Pixels';

fig_handle = gcf;


set(fig_handle,'units',units);
start_fig = get(fig_handle,'position');
set(fig_handle,'position',[start_fig(1), start_fig(2), fWidthPix, fHeightPix]);

%make the figure's print dimensions match the desired size for file saving
save_screenDPI = get(0,'ScreenPixelsPerInch');
set(0,'ScreenPixelsPerInch',dispPix);
%DELME get(0,'ScreenPixelsPerInch')
set(gcf,'PaperUnits','inches','PaperPosition',[0 0 fWidthIn fHeightIn])

% pull the data for plotting
xx = Dim2Data(:,1);
yy = Dim2Data(:,2);

Crux.plotfun(xx,yy)

xlabel(Crux.xlab,'fontsize',fontsz)
ylabel(Crux.ylab,'fontsize',fontsz)
title(Crux.plottitle,'fontsize',fontsz)
set(gca, 'fontsize', fontsz)

%save the figure to a png file
ImageFile = [ImageName '.png'];
print(h,'-dpng',ImageFile,['-r' num2str(resDPI)])

%% Create Image Map -- find the pixel locations of the data in the figure
%The following code is derived from adam@bigbro.biophys.cornell.edu
%(Adam C. Finnefrock)
%http://www.mathworks.com/matlabcentral/newsreader/view_thread/12571

units = 'Pixels';

%Axes locations
axes_handle = gca;
xlim = get(axes_handle, 'XLim');
ylim = get(axes_handle, 'YLim');

save_axes_units = get(axes_handle, 'Units');
set(axes_handle, 'Units', units);
axes_position_in_units = get(axes_handle,'Position');
set(axes_handle, 'Units', save_axes_units)

originx = xlim(1);
originy = ylim(1);
cornerx = xlim(2);
cornery = ylim(2);
scalex = cornerx-originx;
scaley = cornery-originy;
normalized_position(:,1) = (Dim2Data(:,1) - originx) ./ scalex;
normalized_position(:,2) = (Dim2Data(:,2) - originy) ./ scaley;

unitsoriginx = axes_position_in_units(1)-1;
unitsoriginy = axes_position_in_units(2);
unitsscalex = axes_position_in_units(3);
unitsscaley = axes_position_in_units(4);


% %% Create Pixel Map of PNG with respect to data points
% xdata
TheMAP(:,1) = (normalized_position(:,1) .* unitsscalex) + unitsoriginx;
% ydata
%   html imagemaps start from the top, so location is total height - position
TheMAP(:,2) = fHeightPix-((normalized_position(:,2) .* unitsscaley) + unitsoriginy)+1;

TheMAP = round(TheMAP);

%restore screen DPI
set(0,'ScreenPixelsPerInch',save_screenDPI);


%% Create HTML file
% %% Create html header
filename = [ImageName '.html'];

%using 'w' here allows me to overwrite possible pre-existing file
fid = fopen(filename,'w');
fprintf(fid,'%s',['<!DOCTYPE html><html><head><title>' ImageName '</title></head><body>']);
fclose(fid);


fid = fopen(filename,'a');

% %% Write javascript for imagemap highlighting and html style
%When the users mouseover the image with image-map links, the links trigger
%the javascript. The links have syntax 'ref1', 'ref2', etc....
%The javascript function first renders the background of every link as
%white, then it pick the clicked link and highlights its background.

%read the clicked link (text)
fprintf(fid,'%s\r\n','<SCRIPT>');
    fprintf(fid,'%s\r\n','  function highlight(text){');
    fprintf(fid,'%s\r\n','var txt = "tag"+text;');
%write all the blurbs and links background as white
for ii = 1:lenData
    fprintf(fid,'%s\r\n',['document.getElementById(''','tag' refs{ii} '''',').style.backgroundColor = "white";']);
end
%write the chosen link's background as grey
fprintf(fid,'%s\r\n',' document.getElementById(txt).style.backgroundColor = "#bbbbcc"}');
%close java script code
fprintf(fid,'%s\r\n','</SCRIPT><style>');
%add style to html page (indent)
%<div> are the source list elements
fprintf(fid,'%s\r\n','div {margin-left:2cm;width:800px}');
%<h1> is the title
fprintf(fid,'%s\r\n','h1 {margin-left:2cm;width:800px}');
%<p> is the image
fprintf(fid,'%s\r\n','p {margin-left:2cm;}</style>');

% %% write html to display image & imagemap
fprintf(fid,'%s\r\n',['<h1>' Crux.title '</h1>']);
%display image in <p> element
fprintf(fid,'%s\r\n',['<p><img src="' ImageFile '" width="' num2str(fWidthPix) '" height="' num2str(fHeightPix) '" usemap="#' ImageName '"></p>']);
%space to make html more pleasing
fprintf(fid,'%s\r\n', '');
%write the imagemap
fprintf(fid,'%s\r\n',['<map name="' ImageName '">']);
%insert imagemap elements for each datapoint
for ii = 1:lenData
    fprintf(fid,'%s\r\n',['<area shape="circle" coords="' num2str(TheMAP(ii,1)) ',' num2str(TheMAP(ii,2)) ',' num2str(clickrad) '" href="' Crux.links{ii} '"   target="_blank" onMouseOver="highlight(''', refs{ii} '''',')" >']);
end
fprintf(fid,'%s\r\n','</map>');

% %% display list of attributed data references
% these occupy <div> elements, each with an id of syntax ['tag' refs{ii}]
% e.g. id="tagref1"
for ii = 1:lenData
    fprintf(fid,'%s\r\n',['<div id="tag' refs{ii} '">  ' htmllinks{ii} '      '  Crux.blurbs{ii} ' </div>']);
end


% %% html footer
%close out the html page nicely
formatOut = 'mm/dd/yy';
fprintf(fid,'%s\r\n',['</br></br><hr><footer><div>This page was created on: ' datestr(now,formatOut) '</div></footer>']);
fprintf(fid,'%s\r\n',['</body>' '</html>']);

% %% close the html file just written
fclose(fid);

%% Create README txt file with only the imagemap html
txtfilename = ['README_' ImageName '.txt'];
%using 'w' here allows me to overwrite possible pre-existing file
tid = fopen(txtfilename,'w'); 
fprintf(tid,'%s\n','Instructions for using the outputs of AttributedPlotHtml');
fclose(tid);

% %% General instructions in README file
tid = fopen(txtfilename,'a');
fprintf(tid,'%s\r\n', '');
fprintf(tid,'%s\r\n', 'Your Unique Outputs:');
fprintf(tid,'%s\r\n', ['  ' ImageFile]);
fprintf(tid,'%s\r\n', '   - a png file with the MatLab figure in png format with mapped pixels');
fprintf(tid,'%s\r\n', ['  ' filename]);
fprintf(tid,'%s\r\n', ['   - an html file with ' ImageFile ' displayed along with an active']);
fprintf(tid,'%s\r\n', '     imagemap that points to a list of sources with links.');
fprintf(tid,'%s\r\n', '');
fprintf(tid,'%s\r\n', '');
fprintf(tid,'%s\r\n', 'Instructions:');
fprintf(tid,'%s\r\n', ['   - copy the two output files (' ImageFile ' & ' filename ')']);
fprintf(tid,'%s\r\n', '     into the same folder on your website. ');
fprintf(tid,'%s\r\n', ['   When you open the new page (' filename ') it will display your']);
fprintf(tid,'%s\r\n', '     image with an active imagemap. You can preview it directly ');...
fprintf(tid,'%s\r\n', '     from MatLab by right-clicking the mouse and');
fprintf(tid,'%s\r\n', '     selecting ''Open outside MatLab''.'); 
fprintf(tid,'%s\r\n', '');
fprintf(tid,'%s\r\n', '');
fprintf(tid,'%s\r\n', '     If you want to manipulate the image and image map yourself,');
fprintf(tid,'%s\r\n', '     here is the html code for displaying the image <img>');
fprintf(tid,'%s\r\n', '     and the html code for the imagemap <map>.');
fprintf(tid,'%s\r\n', ['     You must still copy the image file: ' ImageFile ' into your page`s folder.']);
fprintf(tid,'%s\r\n', '');
fprintf(tid,'%s\r\n', 'HTML code:');
fprintf(tid,'%s\r\n', '');
% %% html code to display image & imagemap
%display image in <p> element
fprintf(tid,'%s\r\n',['<p><img src="' ImageFile '" width="' num2str(fWidthPix) '" height="' num2str(fHeightPix) '" usemap="#' ImageName '"></p>']);
%space to make html more pleasing
fprintf(tid,'%s\r\n', '');
%write the imagemap
fprintf(tid,'%s\r\n',['<map name="' ImageName '">']);
%insert imagemap elements for each datapoint
for ii = 1:lenData
    fprintf(tid,'%s\r\n',['<area shape="circle" coords="' num2str(TheMAP(ii,1)) ',' num2str(TheMAP(ii,2)) ',' num2str(clickrad) '" href="' Crux.links{ii} '" alt="">']);
end
fprintf(tid,'%s\r\n','</map>');
fclose(tid);
%------------- END OF CODE --------------

end

Contact us