function val = dualcursor2(state,deltalabelpos,marker_color,datalabelformatfcnh,axh)
%dualcursor2       Add dual vertical cursors to a plot
%
%Syntax
%   dualcursor2
%   dualcursor2('state');
%   dualcursor2([X1 X2]);
%   dualcursor2('state',deltalabelpos);
%   dualcursor2([X1 X2],deltalabelpos);
%   dualcursor2('update', ...)       %Updates existing cursors when data has changed
%   dualcursor2(..., ..., marker_color_spec);
%   dualcursor2(..., ..., ..., fcnhandle);
%   dualcursor2(..., ..., ..., ..., axh);
%   val = dualcursor2        %return values of the 2 cursors on the current axis
%   val = dualcursor2(h)     %return values of the 2 cursors on the axis or line w/handle h
%
%Description
% Easy Mode:
%  dualcursor2 on    %Turns on data cursors
%  dualcursor2 off   %Turns off data cursors
%  dualcursor2       %Toggles the state of data cursors
%  val = dualcursor2 %Return the coordinates of the 2 cursors
%      val = [x1 y1 x2 y2 slope avg stddev]
%
% Interaction:
%  Click on the cursors to drag them around.
%  Click on the cursor label to reposition.
%  If multiple lines are plotted, click on a line to make it active.
%  Right click on a cursor to:
%     - Export the selected region to the workspace
%       (exports as a structure named cursors)
%     - Export the selected region to a new figure
%     - Export cursor data to workspace
%       (exports as a variable named cursordata = [x1 y1 x2 y2 slope avg stddev])
%     - Remove the cursors from the plot
%  Click on the delta calculation labels to reposition them.
%
% Advanced Options:
% 1.  Specify initial x-coordinates for the cursors
%  dualcursor2([x1 x2]);   %Adds cursors at x1, x2
%
% 2.  Specify the location of the text label for displaying x2-x1, y2-y1 results
%  dualcursor2([],deltalabelpos);   %Specifies the location to display DeltaX
%                                         %and DeltaY calculations
%  deltalabelpos = [DeltaX_x, DeltaX_y; DeltaY_x, DeltaY_y] in normalized axis units
%  default = [.65 -.08;.9 -.08]  puts them just below the lower right-hand corner.
%  If this is too hard, you can also reposition the labels with your mouse!
%
% 3.  Specifying the color and marker for the cursors
%  dualcursor2([],[],marker_color_spec);
%      %Turns on data cursor, using specified marker and color
%      %marker_color_spec is a one or two element string, specifying color and/or marker
%      %style.  >>help plot   for valid marker and color specifiers
%  ex 'go'  - red circles
%     's'   - squares, with default color (red)
%
% 4.  Update the existing cursors when the data in the plot has changed.
%   dualcursor2('update');
%     This mode is useful when using the cursors on a live data stream.
%
%  This simply updates the appropriate values to reflect the latest data.  Here's
%  how to do this:
%    - When you initialize the graphics before taking data, make your initial call
%       to dualcursor2 (dualcursor2 on, for instance)
%    - In the code that updates the graphics display with new data, call
%   dualcursor2 update
%
% 5.  Specify custom formatting for the data label showing individual cursor values
%  This is implemented with a function handle (@).  You provide a handle to a
%  specifically formatted function:
%   dualcursor2(..., ..., ..., fcnhandle)
%  %Specifies the text and formatting for the data label
%  %fcnhandle is a handle to the function that defines the formatting.  This function
%  %must have the following argument syntax:
%       function textstring = mytextstring(xv,yv);
%       Input:
%         xv          (scalar)  The x cursor value
%         yv          (scalar)  The y cursor value
%       Output:
%         textstring  (string)  The formatted text string
%                     {'string'} Cell array of strings for multi-line display
%
%       Example
%       Create the following function.  save as frequencystring.m
%          function textstring = frequencystring(xv,yv);
%          textstring = {['Amp: ' num2str(yv,'%2g') ' dB']
%                        ['f: ' num2str(xv,'%2g') ' Hz'];};
%    %Use this code when you are ready to call dualcursor2
%    fcnhandle = @frequencystring;  %Create handle to your function
%    dualcursor2(..., ..., ..., fcnhandle)
%
% 6.  Add cursors to a specific axis (not necessarily current axis).
%   dualcursor2(..., ..., ..., ..., axh);
%    Adds the cursors to the axis with handle axh
%    This mode is useful when axis handles might be hidden
%
%
% Example
% %Set up some interesting data
%   load handel
%   Ns = 2^12;
%   Y = fft(y,Ns);
%   Y = 2/Ns*abs(Y(1:Ns/2));
%   df = Fs/Ns;
%   f = (0:1:Ns/2-1)*df;
%  %Plot it
%   figure;
%   plot(f,100*[Y sqrt(Y)])
%   title('My cursor example');
%   xlabel('Frequency (Hz)');
%   ylabel('Amplitude');
%   axis([0 1200 0 inf]);
%
% %Turn on cursors
%   dualcursor2
%
% %Turn off cursors
%   dualcursor2 off
%
% %Place cursors at x=300 and x=400, place DeltaX/DeltaY display in the upper left
% %  hand corner, and use a green square for the cursor.
%   dualcursor2([300 400],[.05 1.05; .25 1.05],'gs');
%
% %Move the cursors around. Try moving the data label, too
%
% %Now, wasn't that fun?  Finally, get the current cursor positions
%   val = dualcursor2;
%       %val = [x1 y1 x2 y2 slope avg stddev]
%
%
% NOTE: HandleVisibility of axis must be set to 'on' or 'callback'
%
% see also: DATALABEL, LINELABEL

% This function is provided as an example only.  It has not been
% tested, and therefore, it is not officially supported by The
% MathWorks, Inc.

% Written by Scott Hirsch
% shirsch@mathworks.com
% Copyright 2002-2009 The MathWorks, Inc.
% This is a (major) modfication of datalabel, available at MATLAB Central

% Updated with slope, average, and standard devation by Ari Feldman

%Parse input arguments
%If output argument, return the cursor values

%See if the user specified a formatting function for the datalabel

if nargin<4 || isempty(datalabelformatfcnh)    %Nope.  Use the default one included here.
    datalabelformatfcnh = @local_maketextstring;
end;

if nargout
    if nargin==0    %Use current axis
        h = gca;
    else
        h = state;
        if strcmp(get(h,'Type'),'line');
            h = get(h,'Parent');
        end;
    end;
    cursors = findobj(h,'Tag','Cursor');
    if length(cursors)==2       %Should be empty (no cursors), or length=2
        for ii=1:2
            cn = getappdata(cursors(ii),'CursorNumber');
            ind = (cn-1)*2+1:cn*2;      %Index into val
            val(ind) = getappdata(cursors(ii),'Coordinates');
        end;
            avgh = getappdata(gca,'Avgh_Handle');
            slopeh = getappdata(gca,'Slope_Handle');
            stddevh = getappdata(gca,'Stddev_Handle');
            avgstr=get(avgh,'String');
            slopestr=get(slopeh,'String');
            stddevstr=get(stddevh,'String');
            avgstr=regexp(avgstr,'\=','split');
            slopestr=regexp(slopestr,'\=','split');
            stddevstr=regexp(stddevstr,'\=','split');
            val(end+1)=str2num(slopestr{2});
            val(end+1)=str2num(avgstr{2});
            val(end+1)=str2num(stddevstr{2});
    else
        val = [];
        warning('I could not find any cursors');
    end;
    return
elseif nargin<5 || isempty(axh)    %Did the user specify a handle?
    axh = gca;
end;

%If no input arguments, switch state (turn off/on)
if (nargin==0 & nargout==0) | isempty(state)  %Switch state.  Check current state
    dots = findobj(axh,'Type','line','Tag','Cursor');  %See if there are any cursors
    if isempty(dots)    %None found.  Turn cursors on
        state = 'on';
    else
        state = 'off';
    end;
end;

%Check if the first argument is numeric.  The user is specifying
%  the initial x-coordinates of the markers
if nargin>=1 & isnumeric(state) %First input is x coordinates of markers
    x_init = state(:);

    %error check
    if length(x_init)~=2
        error('First input must be 2 element vector of x coordinates');
    end;
    state = 'on';       %Turn on data cursors.
else        %Default position = 1/3, 2/3 x axis limits
    %    xl = xlim;              %X Limits.  this is the letter L, not the number 1
    if strcmp(get(axh,'Type'),'figure') ||  strcmp(get(axh,'Type'),'uipanel') || strcmp(get(axh,'Type'),'root');    %user clicked on the axis itself; do nothing
        return
    end;

    xl = xlim(axh);
    lim = localObjbounds(axh);  % Problem using objbounds with hggroup objects, so I have a simple version of my own
    lim = lim(1:2);         %x values only
    xl(isinf(xl)) = lim(isinf(xl));
    width = diff(xl);     %Axis width
    x_init = xl(1)+[1/3 2/3]*width;

end;

% Get handle to figure just once
hFig = ancestor(axh,'figure');

switch state
    case 'on'
        %Initialization
        % Set the WindowButtonDownFcn
        % Add the cursors.

        %If there are already some data cursors on this plot, delete them!
        dualcursor2('off',[],[],[],axh);

        %Parse user inputs

        %Check for user input of position for delta labels
        if nargin<2 | isempty(deltalabelpos)
            deltalabelpos = [.65 -.08;.9 -.08;.65 -.12;.9 -.12;.65 -.16];            %Use defaults
            %[x1 y1; x2 y2]
        end;

        %Marker and color specification
        if nargin >= 3 ,
            %Parse marker string.  User might specify color, marker, or both
            colors = 'bgrcmyk';
            markers = '+o*.xsdv^><ph';
            for ii=1:length(marker_color)
                col_ind = strfind(colors,marker_color(ii));
                if ~isempty(col_ind)        %It's a color
                    color = marker_color(ii);
                else                        %Try a marker instead
                    mark_ind = strfind(markers,marker_color(ii));
                    if ~isempty(mark_ind)
                        marker = marker_color(ii);
                    end;
                end;
            end;
        end;

        %Handle default marker and color
        if ~exist('color','var'), color = 'r'; end; %set default
        if ~exist('marker','var'), marker = '*'; end; %set default

        %Add the cursors.
        %Ideally, the user specified the 2 x coordinates.
        %If not, just put the cursors somewhere nice.
        lineh = local_findlines(axh);

        %Line data
        if isempty(lineh)
            x1 = 0;
            y1 = 0;

            %             erasemode = 'normal';       %default
        else

            %if multiple lines, define callback to allow for selection

            set(lineh,'ButtonDownFcn', ...
                'setappdata(get(gco,''Parent''),''SelectedLine'',gco);dualcursor2(''selectline'',[],[],[],get(gco,''Parent''))');

            %set erasemode to xor.  This speeds things up a ton with large data sets
            %             erasemode = get(lineh,'EraseMode');
            %             set(lineh,'EraseMode','xor');

            lineh = min(lineh);           %Lets just use one line.  This was probably added first
            setappdata(axh,'SelectedLine',lineh); %The currently selected line.

            %Why the last line?  Because it is the first one added
            xl = get(lineh,'XData');
            yl = get(lineh,'YData');
            ynew=yl;
        end;

        %Find nearest value on the line
        [xv1,yv1] = local_nearest(x_init(1),xl,yl);
        [xv2,yv2] = local_nearest(x_init(2),xl,yl);

        %Build the string for the data label
        textstring1 = feval(datalabelformatfcnh,xv1,yv1);
        textstring2 = feval(datalabelformatfcnh,xv2,yv2);

        %Add the data label
        th1 = text(xv1,yv1,textstring1,'FontSize',8,'Tag','CursorText','Parent',axh);
        th2 = text(xv2,yv2,textstring2,'FontSize',8,'Tag','CursorText','Parent',axh);

        %For R13 or higher (MATLAB 6.5), use a background color on the text string
        v=ver('MATLAB');
        v=str2num(v.Version(1:3));
        if v>=6.5
            set(th1,'BackgroundColor','y');
            set(th2,'BackgroundColor','y');
        end;

        yl = ylim(axh);
        lim = localObjbounds(axh);
        lim = lim(3:4);     %y values only
        yl(isinf(yl)) = lim(isinf(yl));

        %Add the cursors
        ph1 = line([xv1 xv1 xv1],[yl(1) yv1 yl(2)], ...
            'Color',color, ...
            'Marker',marker, ...
            'Tag','Cursor', ...
            'UserData',[lineh th1], ...
            'LineStyle','-', ...
            'Parent',axh);
        ph2 = line([xv2 xv2 xv2],[yl(1) yv2 yl(2)], ...
            'Color',color, ...
            'Marker',marker, ...
            'Tag','Cursor', ...
            'UserData',[lineh th2], ...
            'LineStyle','-', ...
            'Parent',axh);

        %Add context menu to the cursors
%         cmenu = uicontextmenu('Parent',get(axh,'Parent'));
        cmenu = uicontextmenu('Parent',hFig);
        set([ph1 ph2],'UIContextMenu',cmenu);

        % Define the context menu items
        item1 = uimenu(cmenu, 'Label', 'Export region to workspace', ...
            'Callback', 'dualcursor2(''exportws'',[],[],[],get(gco,''Parent''))');
        item2 = uimenu(cmenu, 'Label', 'Export region to new figure', ...
            'Callback', 'dualcursor2(''exportfig'',[],[],[],get(gco,''Parent''))');
        item3 = uimenu(cmenu, 'Label', 'Export cursor data to workspace', ...
            'Callback', 'dualcursor2(''exportcursor'',[],[],[],get(gco,''Parent''));');
        item4 = uimenu(cmenu, 'Label', 'Turn cursors off', ...
            'Callback', 'dualcursor2(''off'',[],[],[],get(gco,''Parent''))', ...
            'Separator','on');

        setappdata(th1,'Coordinates',[xv1 yv1]);
        setappdata(ph1,'Coordinates',[xv1 yv1]);
        setappdata(th2,'Coordinates',[xv2 yv2]);
        setappdata(ph2,'Coordinates',[xv2 yv2]);
        setappdata(th1,'CursorNumber',1);
        setappdata(ph1,'CursorNumber',1);
        setappdata(th2,'CursorNumber',2);
        setappdata(ph2,'CursorNumber',2);
        setappdata(th1,'FormatFcnH',datalabelformatfcnh);
        setappdata(th2,'FormatFcnH',datalabelformatfcnh);
        setappdata(th1,'Offset',[0 0]);     %Offset for the text label from the data value
        setappdata(th2,'Offset',[0 0]);     %Offset for the text label from the data value

        %     mh = uicontextmenu('Tag','DeleteObject', ...
        %         'Callback','ud = get(gco,''UserData'');delete([gco ud(2)]);');
        %     set([th1 th2],'UIContextMenu',mh);

        set(th1,'UserData',[lineh ph1]);     %Store handle to line
        set(th2,'UserData',[lineh ph2]);     %Store handle to line

        %Calculate Difference
        dx = xv2 - xv1;
        dy = yv2 - yv1;
        xpos1=find(xl==xv1);
        xpos2=find(xl==xv2);
        avg=mean(ynew(xpos1:xpos2));
        slope=dy/dx;
        stddev=std2(ynew(xpos1:xpos1));

        if round2(avg,.01)==0
            acc={'%+.3e'};
        elseif avg/1000>1
            acc={'%+.3e'};
        else
            acc={'%+.3f'};
        end

        %Add display for cursor deltas
        deltah(1) = text(deltalabelpos(1,1),deltalabelpos(1,2),['({x}_{2}-{x}_{1}) = ' num2str(dx,acc{1})], ...
            'Units','Normalized', ...
            'HorizontalAlignment','left', ...
            'Tag','CursorDeltaText', ...
            'FontSize',8, ...
            'Interpreter','tex', ...
            'Parent',axh);      %dx
        deltah(2) = text(deltalabelpos(2,1),deltalabelpos(2,2),['{y}_{2}-{y}_{1} = ' num2str(dy,acc{1})], ...
            'Units','Normalized', ...
            'HorizontalAlignment','left', ...
            'Tag','CursorDeltaText', ...
            'FontSize',8, ...
            'Interpreter','tex', ...
            'Parent',axh);      %dy

        avgh=text(deltalabelpos(3,1),deltalabelpos(3,2),['avg= ' num2str(avg,acc{1})], ...
            'Units','Normalized', ...
            'HorizontalAlignment','left', ...
            'Tag','CursorDeltaText', ...
            'FontSize',8, ...
            'Interpreter','tex', ...
            'Parent',axh);      %dy
        slopeh=text(deltalabelpos(4,1),deltalabelpos(4,2),['slope= ' num2str(slope,acc{1})], ...
            'Units','Normalized', ...
            'HorizontalAlignment','left', ...
            'Tag','CursorDeltaText', ...
            'FontSize',8, ...
            'Interpreter','tex', ...
            'Parent',axh);      %dy
        stddevh=text(deltalabelpos(5,1),deltalabelpos(5,2),['stddev= ' num2str(stddev,'%+.3e')], ...
            'Units','Normalized', ...
            'HorizontalAlignment','left', ...
            'Tag','CursorDeltaText', ...
            'FontSize',8, ...
            'Interpreter','tex', ...
            'Parent',axh);      %dy

        %Set Application Data.
        setappdata(axh,'Delta_Handle',deltah);
        setappdata(axh,'Avgh_Handle',avgh);
        setappdata(axh,'Slope_Handle',slopeh);
        setappdata(axh,'Stddev_Handle',stddevh);
        setappdata(axh,'Marker',marker);
        setappdata(axh,'Color',color);

        set(hFig,'WindowButtonDownFcn','dualcursor2(''down'',[],[],[],get(gco,''Parent''))')
        set(hFig,'DoubleBuffer','on');       %eliminate flicker

    case 'down'      % Execute the WindowButtonDownFcn
        htype = get(gco,'Type');
        tag = get(gco,'Tag');
        marker = getappdata(axh,'Marker');
        color  = getappdata(axh,'Color');

        %If it's a movable object (Cursor, CursorText label, or Cursor Delta Text
        %label), make it movable.
        if strcmp(tag,'CursorText') | strcmp(tag,'Cursor') | strcmp(tag,'CursorDeltaText')
            set(gco,'EraseMode','xor')
            set(gcf,'WindowButtonMotionFcn','dualcursor2(''move'',[],[],[],get(gco,''Parent''))', ...
                'WindowButtonUpFcn','dualcursor2(''up'',[],[],[],get(gco,''Parent''))');
        end;

        if strcmp(tag,'Cursor') %If clicked on a cursor
            %Label the cursor we are moving.  Add a text label just above the plot
            CursorNumber = getappdata(gco,'CursorNumber');
            cnstr = num2str(CursorNumber);

            xl = xlim(axh);
            lim = localObjbounds(axh);
            lim = lim(1:2);     %x values only
            xl(isinf(xl)) = lim(isinf(xl));
            %             yl = lim(3:4);

            xv = getappdata(gco,'Coordinates');
            xv = xv(1);

            %Convert to normalized
            xn = (xv - xl(1))/(xl(2) - xl(1));
            yn = 1.05;

            CNh = text(xn,yn,cnstr, ...
                'Units','Normalized', ...
                'HorizontalAlignment','center', ...
                'Parent',axh);      %dx

            %For R13 or higher (MATLAB 6.5), use a background color on the text string
            v=ver('MATLAB');
            v=str2num(v.Version);
            if v>=6.5
                set(CNh,'BackgroundColor','y');
            end;
            setappdata(gco,'CNh',CNh);

        end

    case 'move'          % Execute the WindowButtonMotionFcn
        htype = get(gco,'Type');
        tag = get(gco,'Tag');
        if ~isempty(gco)

            %Special (simple) case - just repositioning the delta labels
            if strcmp(tag,'CursorDeltaText')    %The cursor delta labels.
                cp = get(axh,'CurrentPoint');
                pt = cp(1,[1 2]);

                %Put into normalized units
                ax = axis;
                lim = localObjbounds(axh);
                ax(isinf(ax)) = lim(isinf(ax));

                pt(1) = (pt(1) - ax(1))/(ax(2)-ax(1));
                pt(2) = (pt(2) - ax(3))/(ax(4)-ax(3));

                set(gco,'Position', [pt 0])
                drawnow
                return
            end;

            %Is this the cursor or the text
            if strcmp(tag,'CursorText')             %The text
                th = gco;
                handles = get(gco,'UserData');
                ph = handles(2);
                slide = 0;      %Don't slide along line; just reposition text
            else                                    %The marker
                ph = gco;
                handles = get(gco,'UserData');
                th = handles(2);
                slide = 1;      %Slide along line to next data point
            end;

            offset = getappdata(th,'Offset');       %Offset from data value

            cp = get(axh,'CurrentPoint');
            pt = cp(1,[1 2]);

            %Constrain to Line
            lh = getappdata(get(th,'Parent'),'SelectedLine');
            %             lh = handles(1);        %Line

            x = cp(1,1);       %first xy values
            y = cp(1,2);       %first xy values

            if slide            %Move to new data value
                xl = get(lh,'XData');
                yl = get(lh,'YData');
                ynew=yl;

                %Get nearest value
                [xv,yv]=local_nearest(x,xl,yl);

                %If we are moving a cursor, must move the cursor number label, too
                if strcmp(tag,'Cursor')
                    %Move the Cursor Number label, too
                    CNh = getappdata(gco,'CNh');
                    pos = get(CNh,'Position');
                    xlm = xlim(axh);
                    lim = localObjbounds(axh);
                    lim = lim(1:2);     %x values only
                    xlm(isinf(xlm)) = lim(isinf(xlm));
                    xn = (xv - xlm(1))/(xlm(2)-xlm(1));
                    set(CNh,'Position',[xn pos(2:3)])
                end;

                yl = ylim(axh);
                lim = localObjbounds(get(lh,'Parent'));
                lim = lim(3:4);     %y values only
                yl(isinf(yl)) = lim(isinf(yl));
                datalabelformatfcnh = getappdata(th,'FormatFcnH');

                textstring = feval(datalabelformatfcnh,xv,yv);
                set(th,'Position', [xv yv 0] + [offset 0],'String',textstring)
                set(ph,'XData',[xv xv xv],'YData',[yl(1) yv yl(2)]);

                setappdata(ph,'Coordinates',[xv yv]);
                setappdata(th,'Coordinates',[xv yv]);

                %Update delta calculation
                cursors = findobj(axh,'Tag','Cursor');
                cn1 = getappdata(cursors(1),'CursorNumber');
                if cn1==2   %Switch order
                    temp = cursors(1);
                    cursors(1) = cursors(2);
                    cursors(2) = temp;
                end;

                deltah = getappdata(axh,'Delta_Handle');    %Handle to cursors
                avgh = getappdata(axh,'Avgh_Handle');
                slopeh = getappdata(axh,'Slope_Handle');
                stddevh= getappdata(axh,'Stddev_Handle');

                %Positions of two dualcursor2s
                xy1 = getappdata(cursors(1),'Coordinates');
                xy2 = getappdata(cursors(2),'Coordinates');

                %Calculate Difference
                dx = xy2(1) - xy1(1);
                dy = xy2(2) - xy1(2);
                xpos1=find(xl==xy1(1));
                xpos2=find(xl==xy2(1));
                avg=mean(ynew(xpos1:xpos2));
                slope=dy/dx;
                stddev=std2(ynew(xpos1:xpos2));

                if round2(avg,.01)==0
                    acc={'%+.3e'};
                elseif avg/1000>1
                    acc={'%+.3e'};
                else
                    acc={'%+.3f'};
                end

                set(deltah(1),'String',['({x}_{2}-{x}_{1}) = ' num2str(dx,acc{1})]);
                set(deltah(2),'String',['({y}_{2}-{y}_{1}) = ' num2str(dy,acc{1})]);
                set(avgh,'String',['avg= ' num2str(avg,acc{1})]);
                set(slopeh,'String',['slope= ' num2str(slope,acc{1})]);
                set(stddevh,'String',['stddev= ' num2str(stddev,'%+.3e')]);

            else                %Just move text around.
                set(th,'Position', [x y 0])
            end;
            drawnow
        end;

    case 'up'           % Execute the WindowButtonUpFcn
        htype = get(gco,'Type');
        tag = get(gco,'Tag');
        if strcmp(tag,'CursorText') | strcmp(tag,'Cursor') | strcmp(tag,'CursorDeltaText');
            set(gco,'EraseMode','Normal')
            set(gcf,'WindowButtonMotionFcn','')

            if strcmp(tag,'CursorText') %If the text label, record it's relative position
                cp = get(axh,'CurrentPoint');
                pt = cp(1,[1 2]);

                coords = getappdata(gco,'Coordinates');
                offset(1) = pt(1) - coords(1);
                offset = pt - coords;
                setappdata(gco,'Offset',offset);
            end;

            if strcmp(tag,'Cursor')        %Delete the temporary cursor number label
                CNh = getappdata(gco,'CNh');
                delete(CNh);
            end;

        end;

    case 'selectline'          % User selected a new line to be active
        %Make the selected line bold
        lh = getappdata(axh,'SelectedLine');
        lw = get(lh,'LineWidth');
        set(lh,'LineWidth',5*lw);
        drawnow

        %Update the cursors
        dualcursor2('update',deltalabelpos,marker_color,datalabelformatfcnh,axh);

        %Put the line back the way you found it!
        set(lh,'LineWidth',lw);

    case 'update'               %Update the cursor value
        %Find the position of the existing cursors

        cursors = findobj(axh,'Tag','Cursor');
        cd1 = getappdata(cursors(1),'Coordinates');
        cd2 = getappdata(cursors(2),'Coordinates');
        cn1 = getappdata(cursors(1),'CursorNumber');
        cn2 = getappdata(cursors(2),'CursorNumber');
        clear x
        x(cn1) = cd1(1);        %x value of cursor number cn1
        x(cn2) = cd2(1);        %x value of cursor number cn2

        lh = getappdata(axh,'SelectedLine');

        handles = get(cursors(cn1),'UserData');
        th1 = handles(2);
        handles = get(cursors(cn2),'UserData');
        th2 = handles(2);

        offset1 = getappdata(th1,'Offset');       %Offset from data value
        offset2 = getappdata(th2,'Offset');       %Offset from data value

        ylm = ylim(axh);
        lim = localObjbounds(get(lh,'Parent'));
        lim = lim(3:4);     %y values only
        ylm(isinf(ylm)) = lim(isinf(ylm));

        xl = get(lh,'XData');
        yl = get(lh,'YData');
        ynew=yl;

        %Get nearest value
        [xv1,yv1]=local_nearest(x(1),xl,yl);
        [xv2,yv2]=local_nearest(x(2),xl,yl);

        datalabelformatfcnh = getappdata(th1,'FormatFcnH');

        %         textstring1 = {['x=' num2str(xv1)];['y=' num2str(yv1)]};
        %         textstring2 = {['x=' num2str(xv2)];['y=' num2str(yv2)]};
        textstring1 = feval(datalabelformatfcnh,xv1,yv1);
        textstring2 = feval(datalabelformatfcnh,xv2,yv2);
        set(th1,'Position', [xv1 yv1 0] + [offset1 0],'String',textstring1)
        set(th2,'Position', [xv2 yv2 0] + [offset2 0],'String',textstring2)
        set(cursors(cn1),'XData',[xv1 xv1 xv1],'YData',[ylm(1) yv1 ylm(2)]);
        set(cursors(cn2),'XData',[xv2 xv2 xv2],'YData',[ylm(1) yv2 ylm(2)]);
        %Update delta calculation
        deltah = getappdata(axh,'Delta_Handle');    %Handle to delta calculation
        avgh = getappdata(axh,'Avgh_Handle');
        slopeh = getappdata(axh,'Slope_Handle');
        stddevh = getappdata(axh,'Stddev_Handle');

        %                 %Positions of two dualcursor2s
        xy1 = getappdata(cursors(1),'Coordinates');
        xy2 = getappdata(cursors(2),'Coordinates');

        %Calculate Difference
        dx = xv2 - xv1;
        dy = yv2 - yv1;
        xpos1=find(xl==xv1);
        xpos2=find(xl==xv2);
        avg=mean(ynew(xpos1:xpos2));
        slope=dy/dx;
        stddev=std2(ynew(xpos1:xpos2));

        if round2(avg,.01)==0
            acc={'%+.3e'};
        elseif avg/1000>1
            acc={'%+.3e'};
        else
            acc={'%+.3f'};
        end

        set(deltah(1),'String',['{x}_{2}-{x}_{1} ' num2str(dx,acc{1})]);
        set(deltah(2),'String',['{y}_{2}-{y}_{1} ' num2str(dy,acc{1})]);
        set(avgh,'String',['avg= ' num2str(avg,acc{1})]);
        set(slopeh,'String',['Slope= ' num2str(slope,acc{1})]);
        set(stddevh,'String',['stddev= ' num2str(stddev,'%+.3e')]);

    case 'exportws'     %Export selected region to workspace
        [xd,yd] = local_extractregion(axh);

        %If there's only one line, don't make the user hassle with cell arrays
        if length(xd)==1
            xd = xd{1};
            yd = yd{1};
        end;

        cursors.xd = xd;
        cursors.yd = yd;

        assignin('base','cursors',cursors);
        disp('Variable: cursors created in workspace');

    case 'exportfig'     %Export selected region to a new figure
        %         [xd,yd,proplist,props] = local_extractregion;
        [xd,yd,hgS] = local_extractregion(axh);

        %Create new plot
        fh = figure;
        ax = axes;
        struct2handle(hgS,ax);

        %Get labels from axes, too
        %Clunky, but it seems to work
        %First, create empty title, xlabel, ylabel
        newhandles(1) = title('');
        newhandles(2) = xlabel('');
        newhandles(3) = ylabel('');

        %Get strings from original plot
        props = {'Title','xlabel','ylabel'};
        vals = get(axh,props);
        handles = [vals{:}];
        str = get(handles,'String');

        %Set the new strings to match
        set(newhandles,{'String'},str)

    case 'exportcursor'
        % Get cursor coordinates
        cursordata = dualcursor2(axh);

        % Push the data into the base workspace.
        assignin('base','cursordata',cursordata);
        disp('Variable: cursordata created in workspace');

    case 'off'   % Unset the WindowButton...Fcns
        % set(get(axh,'Parent'),'WindowButtonDownFcn','','WindowButtonUpFcn','')
        set(hFig,'WindowButtonDownFcn','','WindowButtonUpFcn','')

        h1 = findobj(axh,'Tag','CursorText');       %All text
        h2 = findobj(axh,'Tag','Cursor');           %The cursors
        h3 = findobj(axh,'Tag','CursorDeltaText');           %The cursors

        lineh = local_findlines(axh);
        set(lineh,'ButtonDownFcn','');

        %         erasemode = getappdata(axh,'OriginalEraseMode');
        %         if isempty(erasemode), erasemode = 'normal'; end;   %handles first time
        %         set(local_findlines(axh),'EraseMode',erasemode);

        delete([h1;h2;h3]);

end %switch/case on action
end

% function hFig = figHandle(axh)
% % Get the handle to the parent figure
% hFig = ancestor(axh,'figure');
% end

function [xv,yv]=local_nearest(x,xl,yl)
%Inputs:
% x   Selected x value
% xl  Line Data (x)

%Find nearest value of [xl] to (x)
%Special Case: Line has a single non-singleton value
if sum(isfinite(xl))==1
    fin = find(isfinite(xl));
    xv = xl(fin);
    yv = yl(fin);
else
    %Normalize axes
    xlmin = min(xl);
    xlmax = max(xl);
    xln = (xl - xlmin)./(xlmax - xlmin);
    xn = (x - xlmin)./(xlmax - xlmin);

    %Find nearest x value only.
    c = abs(xln - xn);

    [junk,ind] = min(c);

    %Nearest value on the line
    xv = xl(ind);
    yv = yl(ind);
end;
end

function textstring = local_maketextstring(xv,yv)
textstring = {['x = ' num2str(xv,'%2g')];
    ['y = ' num2str(yv,'%2.2g')]};
end

function [xd,yd,hgS] = local_extractregion(axh)
val = dualcursor2(axh);

%Find all lines
lineh = local_findlines(axh);

Nl = length(lineh);

%Get all line properties, so we can reproduce the appearance
hgS = handle2struct(lineh);       %Get properties

xd = get(lineh,'XData');
yd = get(lineh,'YData');

%Figure out the index into these lines that val corresponds to
x1ind = zeros(Nl,1);
x2ind = zeros(Nl,1);

%Special handling for single line case
if Nl==1
    xd= {xd};
    yd = {yd};
end;

for ii = 1:Nl
    x1ind(ii) = max(find(xd{ii}<=val(1)));
    x2ind(ii) = max(find(xd{ii}<=val(3)));

    %Keep data from this region only
    xd{ii} = xd{ii}(x1ind(ii):x2ind(ii));
    yd{ii} = yd{ii}(x1ind(ii):x2ind(ii));

    %Update handle structure, to make plotting really easy
    hgS(ii).properties.XData = xd{ii};
    hgS(ii).properties.YData = yd{ii};

end;
end

function lineh = local_findlines(axh);
lineh = findobj(axh,'Type','line');        %Find a line to add cursor to
dots = findobj(axh,'Type','line','Tag','Cursor');  %Ignore existing cursors
lineh = setdiff(lineh,dots);

%Ignore lines with only one or two values - these are probably annotations of some
%sort
xdtemp = get(lineh,'XData');
linehtemp = lineh;
lineh=[];
if ~iscell(xdtemp)      %If there's only one line, force data into a cell array
    xdtemp = {xdtemp};
end;

for ii=1:length(xdtemp);
    if length(xdtemp{ii})>2
        lineh = [lineh; linehtemp(ii)];
    end;
end;
end

function lim = localObjbounds(axh);
% Get x limits of all data in axes axh
kids = get(axh,'Children');
xmin = Inf; xmax = -Inf;
ymin = Inf; ymax = -Inf;
for ii=1:length(kids)
    try % Pass through if can't get data.  hopefully we hit at least one
        xd = get(kids(ii),'XData');
        xmin = min([xmin min(xd(:))]);
        xmax = max([xmax max(xd(:))]);

        yd = get(kids(ii),'YData');
        ymin = min([ymin min(yd(:))]);
        ymax = max([ymax max(yd(:))]);
    end
end
% Nuclear option, in case things went really bad
xmin(xmin==Inf) = 0;  xmax(xmax==-Inf) = 1;
ymin(ymin==Inf) = 0;  ymax(ymax==-Inf) = 1;

lim = [xmin xmax ymin ymax];
end


function L = isinf(x)
%PREAL/ISINF    Overloaded ISINF function for class preal.

L=isinf(double(x));


function maxfig(varargin)
% maxfig(fig,extend,mode)  MAXimize a FIGure to fill the screen.
%   Subsequent calls will restore the maximized figure to its previous state.
%   Examples:
%       maxfig, maxfig(3,1+i), maxfig([],-1), maxfig('normal')
%   "fig" (first numeric input) is the handle of the figure to maximize
%       (default is current figure).
%   "extend" (second numeric input) is a complex number specifying how
%       figures are to be created on the extended desktop.
%       Examples: +1/-1 is one screen to the right/left,
%                 0 is the primary screen (default),
%                 +i is one screen up,
%                 -1-0.5i is half a screen down and to the left, etc...
%   "mode" is a string specifying whether to fully maximize the figure
%       (borders extend beyond the monitor, menu and tool bars are removed)
%       or set to normal mode with borders, menu & toolbars displayed.
%       Value for maximize mode is any of {m,max,y,yes,t,true}(default).
%       Value for normal mode is any of {n,normal,no,f,false}.

%   Copyright 2006 Mirtech, Inc.
%   created 08/23/2006  by Mirko Hrovat on Matlab Ver. 7.2
%   Mirtech, Inc.   email: mhrovat@email.com
% More notes:
% Will work with docked figures.
% Inspired by MAXFIGSIZE (ID 3036) by Duane Hanselman.
% Extended monitors must have the same resolution as the primary monitor.
% The figure properties, TAG and USERDATA, are used to keep track of the
% maximized figure.

% --------- Key Constants -----------
% To allow for user or OS borders set the appropriate value in pixels.
% For example one might want to set the bottomborder for the windows
% taskbar (try a value of 40).
topborder       =0;
bottomborder    =0;
rightborder     =0;
leftborder      =0;
% Border properties for figures - Adjust if needed.
% determined by the difference between OuterPosition and Position values.
% GETFIGDIM can return these values for your system.
figureborder    =5;
titleheight     =26;        %#ok
% ----------------------------------

fullflag=1;     % set default state for maximization choice
extend=[];
% just in case, check all figures for 'MaxFig' tag
set(0,'ShowHiddenHandles','on')
fig= findobj('Tag','MaxFig');
set(0,'ShowHiddenHandles','off')
% If "MaxFig" figure is found then reset size to original values
if ~isempty(fig),
    set(fig,'Tag','')
    userdata=get(fig,'UserData');
    set(fig,'Units',userdata{1},'OuterPosition',userdata{2});
    set(fig,'MenuBar',userdata{3},'ToolBar',userdata{4},...
        'WindowStyle',userdata{5});
    drawnow
end
if nargin==0,
    if ~isempty(fig),
        return
    % return if no arguments, maxfig is only resetting the figure.
    end
else
    count=0;
    for n=1:length(varargin),
        arg=varargin{n};
        if isnumeric(arg),      % note "empty" is also considered to be numeric!
            count=count+1;
            switch count
                case 1
                    fig=arg;
                case 2
                    extend=arg;
            end  % switch count
        elseif ischar(arg),
            if any(strcmpi(arg,{'y','yes','t','true','m','max'})),
                fullflag=1;
            elseif any(strcmpi(arg,{'n','no','f','false','normal'})),
                fullflag=0;
            end
        end
    end  % for
end  % if nargin
if isempty(fig),        fig=gcf;    end
if isempty(extend),     extend=0;   end

% Check WindowStyle property
winstyle=get(fig,'WindowStyle');
if strcmpi(winstyle,'modal'),
    error('  Cannot maximize this figure.')
end

% Get screen dimensions. Note that multiple monitors are assumed to have
% the same resolution.
set(0,'Units','pixels');
scnsize=get(0,'ScreenSize');
scnwidth=scnsize(3)-leftborder-rightborder;
scnheight=scnsize(4)-topborder-bottomborder;

% Calculate offsets for multiple monitors.
offx=scnsize(3)*real(extend)+leftborder;
offy=scnsize(4)*imag(extend)+bottomborder;

% Save properties for figure in UserData field
set(fig,'Tag','MaxFig')
menbar=get(fig,'MenuBar');
tbar=get(fig,'ToolBar');
set(fig,'UserData',{get(fig,'Units'), get(fig,'OuterPosition'),...
    menbar,tbar,winstyle})

if fullflag
    tbar='none';
    menbar='none';
    offx=offx-figureborder;
    offy=offy-figureborder;
    scnwidth=scnwidth+2*figureborder;
    scnheight=scnheight+2*figureborder;
%    scnheight=scnheight+2*figureborder+titleheight;
% The above seems to create problems as results don't match settings.
%   The values seem to wrap around. So it looks like there is no simple
%   way to get rid of the title bar in Matlab.
end

pos=[offx+1,offy+1,scnwidth,scnheight];
% Move, size figure and modify properties as needed.
if strcmpi(winstyle,'docked'),
    set(fig,'WindowStyle','normal')
    drawnow
end
set(fig,'Units','pixels', ...
        'OuterPosition',pos,...
        'MenuBar',menbar,...
        'ToolBar',tbar);
figure(fig)                 % bring figure to front.
end


classdef CoreSystemUtilities
    % CoreSystemUtilities. Utility functions relating to the hardware or operating system.
    %
    %
    %     Licence
    %     -------
    %     Part of CoreMat. https://github.com/tomdoel/coremat
    %     Author: Tom Doel, 2013.  www.tomdoel.com
    %     Distributed under the MIT licence. Please see website for details.
    %

    methods (Static)

        function uid = GenerateUid()
            % Creates a random unique identifier

            % On unix systems, if java is not running we can use the system
            % command
            if isunix && ~usejava('jvm')
                [status, uid] = system('uuidgen');
                if status ~= 0
                    error('Failure running uuidgen');
                end
            else
                uid = char(java.util.UUID.randomUUID);
            end
        end

        function hash = StringToHash(string)
            % Performs an SHA hash on a string
            persistent messageDigest
            if isempty(messageDigest)
                messageDigest = java.security.MessageDigest.getInstance('SHA-256');
            end
            hash = sprintf('%2.2x', typecast(messageDigest.digest(uint8(string)), 'uint8')');
        end

        function dimensions = GetMonitorDimensions()
            % Gets the resolution of the screen

            if usejava('jvm')
                d = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
                dimensions = [d.width, d.height];
            else
                dimensions = get(0, 'ScreenSize');
                dimensions = dimensions(3:4);
            end
        end

        function bytes_in_type = GetBytesInType(type_string)
            % Returns the number of bytes in the given Matlab type

            switch type_string
                case {'int8', 'uint8'}
                    bytes_in_type = 1;
                case {'uint16', 'int16'}
                    bytes_in_type = 2;
                case {'uint32', 'int32'}
                    bytes_in_type = 4;
                case {'uint64', 'int64'}
                    bytes_in_type = 8;
                otherwise
                    error('CoreSystemUtilities:GetBytesInType', 'Unknown number type');
            end
        end

        function computer_endian = GetComputerEndian()
            % Returns an enumeration for the endian of this computer

            [~, ~, computer_endian_str] = computer;

            switch computer_endian_str
                case 'B'
                    computer_endian = CoreEndian.BigEndian;
                case 'L'
                    computer_endian = CoreEndian.LittleEndian;
                otherwise
                    error('CoreSystemUtilities:GetComputerEndian', 'Unknown endian');
            end
        end

        function DeleteIfValidObject(object_handle)
            % Deletes an object

            if ~isempty(object_handle)
                if isvalid(object_handle)
                    delete(object_handle);
                end
            end
        end

        function DeleteIfGraphicsHandle(handle)
            % Removes a graphics handle

            if ishandle(handle)
                delete(handle);
            end
        end

        function colormap = BackwardsCompatibilityColormap()
            % Returns a colormap which replicates the default colormap from
            % Matlab versions pre-hg2

            old_colormap = [0 0 1; 0 0.5 0; 1 0 0; 0 0.75 0.75; 0.75 0 0.75; 0.75 0.75 0; 0.25 0.25 0.25];
            colormap = repmat(old_colormap, [9, 1]);
            colormap = [colormap; [0 0 1]];
        end

        function [major_version, minor_version] = GetMatlabVersion()
            % Returns the major and minor version numbers of Matlab

            [matlab_version, ~] = version;
            version_matrix = sscanf(matlab_version, '%d.%d.%d.%d');
            major_version = version_matrix(1);
            minor_version = version_matrix(2);
        end

        function toolbox_installed = IsImageProcessingToolboxInstalled()
            % Returns true if the Matlab image processing toolbox is
            % installed

            matlab_version = ver;
            toolbox_installed = any(strcmp('Image Processing Toolbox', {matlab_version.Name}));
        end

        function toolbox_licensed = IsImageProcessingToolboxLicensed()
            % Returns true if the Matlab image processing toolbox has a valid licence

            [error_code, error_message] = license('checkout', 'image_toolbox');
            toolbox_licensed = error_code == 1;
        end

        function path_to_executable = FindFirstExecutableOnPath(executable_name)
            % Returns the path of the first executable found on the system
            % path with the specified name

            if ispc
                [status, path_to_executable] = system(['where ' executable_name]);
            else
                [status, path_to_executable] = system(['which ' executable_name]);
            end

            if status == 0
                % Extract out the first executable, if more than one are
                % returned (which can happen with where on Windows)
                path_to_executable = CoreTextUtilities.RemoveNonprintableCharactersAndStrip(strtok(path_to_executable, char(13)));
            else
                path_to_executable = [];
            end
        end
    end
end


function out=real(x)

precision=x(1).precision;
out_rval=cell(size(x));
out_ival=cell(size(x));

for ii=1:numel(x)
 imag=false;
 [out_rval{ii},xival]=getVals(x,ii);
end % for ii=1:max(ex,
out=class(struct('rval',out_rval,...
                 'ival',out_ival,...
                 'precision',precision),'mp');


% Compile libraries and download network

[home_dir, name, ext] = fileparts(mfilename('fullpath'));
% donwload network
    mkdir model
    cd model/
    if ~(exist('imagenet-vgg-m-2048.mat', 'file') == 2)
        disp('Downloading the network "imagenet-vgg-m-2048.mat" from "http://www.vlfeat.org/matconvnet/models/imagenet-vgg-m-2048.mat"...')
        urlwrite('http://www.vlfeat.org/matconvnet/models/imagenet-vgg-m-2048.mat', 'imagenet-vgg-m-2048.mat')
        disp('Done!')
    end
    if ~(exist('imagenet-vgg-verydeep-16.mat', 'file') == 2)
        disp('Downloading the network "imagenet-vgg-verydeep-16.mat" from "http://www.vlfeat.org/matconvnet/models/imagenet-vgg-verydeep-16.mat"...')
        urlwrite('http://www.vlfeat.org/matconvnet/models/imagenet-vgg-verydeep-16.mat', 'imagenet-vgg-verydeep-16.mat')
        disp('Done!')
    end
    cd(home_dir)
% compile matconvnet
    setup_path();
    vl_setupnn();
    try
        disp('Trying to compile MatConvNet with GPU support')
        vl_compilenn('enableGpu', true, ...
               'cudaRoot', '/usr/local/cuda', ...
               'cudaMethod', 'nvcc')
    catch err
        disp('Installation failed!')
        warning('ASRCF:install', 'Could not compile MatConvNet with GPU support.\nVisit http://www.vlfeat.org/matconvnet/install/ for instructions of how to compile MatConvNet.\n');
    end
    status = movefile('mex/vl_*.mex*');
    cd(home_dir)


function imdb = cnn_setup_data_voc07_ssw(varargin)
%CNN_SETUP_DATE_VOC07_SSW  Setup PASCAL VOC 2007 data with precomputed SSW proposals
%
% Copyright (C) 2016 Hakan Bilen.
% All rights reserved.
%
% This file is part of the VLFeat library and is made available under
% the terms of the BSD license (see the COPYING file).

opts.sswDir = fullfile('data','SSW') ;
opts.dataDir = 'data' ;
opts.addFlipped = true ;
opts.useDifficult = true ;
opts.fgThresh = 0.5 ;
opts.bgThreshHi = 0.5 ;
opts.bgThreshLo = 0.1 ;
opts = vl_argparse(opts, varargin) ;

%% Get selective search windows
files = {...
  'SelectiveSearchVOC2007trainval.mat', ...
  'SelectiveSearchVOC2007test.mat'} ;

if ~exist(opts.sswDir, 'dir')
  mkdir(opts.sswDir) ;
end

for i=1:numel(files)
  outPath = fullfile(opts.sswDir, files{i}) ;
  if ~exist(outPath, 'file')
    url = sprintf('http://koen.me/research/downloads/%s',files{i}) ;
    fprintf('Downloading %s to %s\n', url, outPath) ;
    urlwrite(url,outPath) ;
  end
end

%% Get image names and gt boxes.
imdb = cnn_setup_data_voc07(...
  'dataDir', opts.dataDir, ...
  'useDifficult', opts.useDifficult, ...
  'addFlipped', opts.addFlipped) ;

%% Load precomputed object proposals
train = load(fullfile(opts.sswDir, files{1})) ;
test = load(fullfile(opts.sswDir, files{2})) ;

% Check that all proposals are correctly matched to an image in imdb
assert(isempty(...
  setxor(vertcat(train.images,test.images), cellfun(@(x)x(1:6),imdb.images.name,'uniformoutput',0)))) ;

if opts.addFlipped
  boxes = horzcat(train.boxes,train.boxes,test.boxes) ;
  imnames = vertcat(train.images,train.images,test.images) ;
else
  boxes = horzcat(train.boxes,test.boxes) ;
  imnames = vertcat(train.images,test.images) ;
end
assert(numel(boxes)==numel(imdb.images.name)) ;

% Sort proposals by ascending image name, as this is also the order in imdb
[imnames,si] = sort(imnames);
boxes = boxes(si);

% Transpose XY in proposals
for i=1:numel(boxes)
  boxes{i} = boxes{i}(:,[2 1 4 3]);
end

% Check boxes and find corresponding image
for i=1:numel(imdb.images.name)

  bbox = boxes{i};
  assert(strcmp(imnames{i},imdb.images.name{i}(1:end-4)));
  assert(all(all(bbox(:,[1 2]) <= bbox(:,[3 4])))) ;
  assert(all(all(1 <= bbox & bsxfun(@le, bbox, imdb.images.size(i,[1 2 1 2]))))) ;

  % Flip the proposals if needed
  if imdb.boxes.flip(i)
    imageWidth = imdb.images.size(i,1) ;
    bbox(:,[3 1]) = imageWidth - bbox(:,[1 3]) + 1 ;
  end

  boxes{i} = bbox ;
end

imdb = attach_proposals(imdb,boxes,opts.fgThresh,opts.bgThreshHi,opts.bgThreshLo);
imdb = add_bboxreg_targets(imdb);

if 0
  for i = 1:100
    for c = 1:21
      sel = find(imdb.boxes.plabel{i} == c) ;
      if isempty(sel), continue ; end
      im = imread(fullfile(imdb.imageDir, imdb.images.name{i})) ;
      if imdb.boxes.flip(i), im = fliplr(im) ; end
      pbox = imdb.boxes.pbox{i}(sel,:) ;
      clf ; bbox_draw(im, pbox) ;
      title(sprintf('Class %d', c)) ;
      keyboard
    end
  end
end


function datToNPY(inFilename, outFilename, dataType, shape, varargin)
% function datToNPY(inFilename, outFilename, shape, dataType, [fortranOrder, littleEndian])
%
% make a NPY file from a flat binary file, given that you know the shape,
% dataType, ordering, and endianness of the flat binary file.
%
% The point here is you don't want to read in all the data from the
% existing binary file - instead you can just create the appropriate header
% and then concatenate it with the data.
%
% ** completely untested

if ~isempty(varargin)
    fortranOrder = varargin{1}; % must be true/false
    littleEndian = varargin{2}; % must be true/false
else
    fortranOrder = true;
    littleEndian = true;
end

header = constructNPYheader(dataType, shape, fortranOrder, littleEndian);

% ** TODO: need to put the header into a temp file instead, in case the
% outFilename is the same as the inFilename (and then delete the temp file
% later)
fid = fopen(tempFilename, 'w');
fwrite(fid, header, 'uint8');
fclose(fid)

str = computer;
switch str
    case {'PCWIN', 'PCWIN64'}
        [~,~] = system(sprintf('copy /b %s+%s %s', tempFilename, inFilename, outFilename));
    case {'GLNXA64', 'MACI64'}
        [~,~] = system(sprintf('cat %s %s > %s', tempFilename, inFilename, outFilename));

    otherwise
        fprintf(1, 'I don''t know how to concatenate files for your OS, but you can finish making the NPY youself by concatenating %s with %s.\n', tempFilename, inFilename);
end


function t = isascii(c)
%ISASCII True for decimal digits.
%
%   For a string C, ISASCII(C) is 1 for any ASCII character code between 0
%   and 127, inclusive, and 0 otherwise.
%
%   See also: ISALNUM, ISALPHA, ISDIGIT, ISLOWER, ISPRTCHR, ISUPPER,
%   ISXDIGIT.

%   Author:      Peter J. Acklam
%   Time-stamp:  2002-03-03 13:51:07 +0100
%   E-mail:      pjacklam@online.no
%   URL:         http://home.online.no/~pjacklam

   error(nargchk(1, 1, nargin));

   t = ischar(c) & ( 0 <= c ) & ( c <= 127 );


% function [img]=jp2read(filename)
%
% reads a JPEG2000 compliant file and stores information
% in a matlab image

function img=jp2read(filename)

    import jj2000.disp.*;
    import jj2000.j2k.util.*;
    import jj2000.j2k.decoder.*;
    import java.awt.image.*;
    import java.awt.*;
    import java.io.*;

    defpl=ParameterList();
    params=Decoder.getAllParameters();

    for i=1:size(params,1)
        if ne(params(i,4),'')
            defpl.setProperty(params(i,1),params(i,4));
        end
    end

    defpl.setProperty('i',filename);
    defpl.setProperty('v','on');
    defpl.setProperty('debug','on');

    isp=ImgScrollPane();

    d=Decoder(ParameterList(defpl),isp);

    ml=StreamMsgLogger(FileOutputStream('out.log'), ...
        FileOutputStream('err.log'),78);

    FacilityManager.registerMsgLogger('',ml);

    d.run();

    image=isp.getImage();

    w=image.getWidth();
    h=image.getHeight();

    pg=PixelGrabber(image,0,0,w,h,false);
    pg.startGrabbing();
    a=pg.getPixels();

    img=java2im(a,h,w);
return


function [net,stats] = cnn_train_dag(net, imdb, getBatch, varargin)
%CNN_TRAIN_DAG Demonstrates training a CNN using the DagNN wrapper
%    CNN_TRAIN_DAG() is similar to CNN_TRAIN(), but works with
%    the DagNN wrapper instead of the SimpleNN wrapper.

% Copyright (C) 2014-16 Andrea Vedaldi.
% All rights reserved.
%
% This file is part of the VLFeat library and is made available under
% the terms of the BSD license (see the COPYING file).
addpath(fullfile(vl_rootnn, 'examples'));

opts.expDir = fullfile('data','exp') ;
opts.continue = true ;
opts.batchSize = 256 ;
opts.numSubBatches = 1 ;
opts.train = [] ;
opts.val = [] ;
opts.gpus = [] ;
opts.prefetch = false ;
opts.numEpochs = 300 ;
opts.learningRate = 0.001 ;
opts.weightDecay = 0.0005 ;

opts.solver = @solver.sgd; % Empty array - optimised SGD solver
[opts, varargin] = vl_argparse(opts, varargin);
if isempty(opts.solver)
  opts.solverOpts.momentum = 0.9;
else
  assert(isa(opts.solver, 'function_handle') && nargout(opts.solver) == 2,...
    'Invalid solver - a function handle with two outputs expected.');
  % A call without any input arg - def opts
  opts.solverOpts = opts.solver();
end

opts.saveSolverState = true ;
opts.randomSeed = 0 ;
opts.profile = false ;
opts.parameterServer.method = 'mmap' ;
opts.parameterServer.prefix = 'mcn' ;

opts.derOutputs = {'objective', 1} ;
opts.extractStatsFn = @extractStats ;
opts.plotStatistics = true;
opts = vl_argparse(opts, varargin) ;

if ~exist(opts.expDir, 'dir'), mkdir(opts.expDir) ; end
if isempty(opts.train), opts.train = find(imdb.images.set==1) ; end
if isempty(opts.val), opts.val = find(imdb.images.set==2) ; end
if isnan(opts.train), opts.train = [] ; end
if isnan(opts.val), opts.val = [] ; end

% -------------------------------------------------------------------------
%                                                            Initialization
% -------------------------------------------------------------------------

evaluateMode = isempty(opts.train) ;
if ~evaluateMode
  if isempty(opts.derOutputs)
    error('DEROUTPUTS must be specified when training.\n') ;
  end
end

% -------------------------------------------------------------------------
%                                                        Train and validate
% -------------------------------------------------------------------------

modelPath = @(ep) fullfile(opts.expDir, sprintf('net-epoch-%d.mat', ep));
modelFigPath = fullfile(opts.expDir, 'net-train.pdf') ;

start = opts.continue * findLastCheckpoint(opts.expDir) ;
if start >= 1
  fprintf('%s: resuming by loading epoch %d\n', mfilename, start) ;
  [net, state, stats] = loadState(modelPath(start)) ;
else
  state = [] ;
end

for epoch=start+1:opts.numEpochs

  % Set the random seed based on the epoch and opts.randomSeed.
  % This is important for reproducibility, including when training
  % is restarted from a checkpoint.

  rng(epoch + opts.randomSeed) ;
  prepareGPUs(opts, epoch == start+1) ;

  % Train for one epoch.
  params = opts ;
  params.epoch = epoch ;
  params.learningRate = opts.learningRate(min(epoch, numel(opts.learningRate))) ;
  params.train = opts.train(randperm(numel(opts.train))) ; % shuffle
  params.val = opts.val(randperm(numel(opts.val))) ;
  params.imdb = imdb ;
  params.getBatch = getBatch ;

  if numel(opts.gpus) <= 1
    [net, state] = processEpoch(net, state, params, 'train') ;
    [net, state] = processEpoch(net, state, params, 'val') ;
    if ~evaluateMode
      saveState(modelPath(epoch), net, state) ;
    end
    lastStats = state.stats ;
  else
    spmd
      [net, state] = processEpoch(net, state, params, 'train') ;
      [net, state] = processEpoch(net, state, params, 'val') ;
      if labindex == 1 && ~evaluateMode
        saveState(modelPath(epoch), net, state) ;
      end
      lastStats = state.stats ;
    end
    lastStats = accumulateStats(lastStats) ;
  end

  stats.train(epoch) = lastStats.train ;
  stats.val(epoch) = lastStats.val ;
  clear lastStats ;
  saveStats(modelPath(epoch), stats) ;

  if opts.plotStatistics
    switchFigure(1) ; clf ;
    plots = setdiff(...
      cat(2,...
      fieldnames(stats.train)', ...
      fieldnames(stats.val)'), {'num', 'time'}) ;
    for p = plots
      p = char(p) ;
      values = zeros(0, epoch) ;
      leg = {} ;
      for f = {'train', 'val'}
        f = char(f) ;
        if isfield(stats.(f), p)
          tmp = [stats.(f).(p)] ;
          values(end+1,:) = tmp(1,:)' ;
          leg{end+1} = f ;
        end
      end
      subplot(1,numel(plots),find(strcmp(p,plots))) ;
      plot(1:epoch, values','o-') ;
      xlabel('epoch') ;
      title(p) ;
      legend(leg{:}) ;
      grid on ;
    end
    drawnow ;
    print(1, modelFigPath, '-dpdf') ;
  end
end

% With multiple GPUs, return one copy
if isa(net, 'Composite'), net = net{1} ; end

% -------------------------------------------------------------------------
function [net, state] = processEpoch(net, state, params, mode)
% -------------------------------------------------------------------------
% Note that net is not strictly needed as an output argument as net
% is a handle class. However, this fixes some aliasing issue in the
% spmd caller.

% initialize with momentum 0
if isempty(state) || isempty(state.solverState)
  state.solverState = cell(1, numel(net.params)) ;
end

% move CNN  to GPU as needed
numGpus = numel(params.gpus) ;
if numGpus >= 1
  net.move('gpu') ;
  state.momentum = cellfun(@gpuArray, state.momentum, 'uniformoutput', false) ;
end
if numGpus > 1
  parserv = ParameterServer(params.parameterServer) ;
  net.setParameterServer(parserv) ;
else
  parserv = [] ;
end

% profile
if params.profile
  if numGpus <= 1
    profile clear ;
    profile on ;
  else
    mpiprofile reset ;
    mpiprofile on ;
  end
end

num = 0 ;
epoch = params.epoch ;
subset = params.(mode) ;
adjustTime = 0 ;

stats.num = 0 ; % return something even if subset = []
stats.time = 0 ;

start = tic ;
for t=1:params.batchSize:numel(subset)
  fprintf('%s: epoch %02d: %3d/%3d:', mode, epoch, ...
          fix((t-1)/params.batchSize)+1, ceil(numel(subset)/params.batchSize)) ;
  batchSize = min(params.batchSize, numel(subset) - t + 1) ;

  for s=1:params.numSubBatches
    % get this image batch and prefetch the next
    batchStart = t + (labindex-1) + (s-1) * numlabs ;
    batchEnd = min(t+params.batchSize-1, numel(subset)) ;
    batch = subset(batchStart : params.numSubBatches * numlabs : batchEnd) ;
    num = num + numel(batch) ;
    if numel(batch) == 0, continue ; end

    inputs = params.getBatch(params.imdb, batch) ;

    if params.prefetch
      if s == params.numSubBatches
        batchStart = t + (labindex-1) + params.batchSize ;
        batchEnd = min(t+2*params.batchSize-1, numel(subset)) ;
      else
        batchStart = batchStart + numlabs ;
      end
      nextBatch = subset(batchStart : params.numSubBatches * numlabs : batchEnd) ;
      params.getBatch(params.imdb, nextBatch) ;
    end

    if strcmp(mode, 'train')
      net.mode = 'normal' ;
      net.accumulateParamDers = (s ~= 1) ;
      net.eval(inputs, params.derOutputs, 'holdOn', s < params.numSubBatches) ;
    else
      net.mode = 'test' ;
      net.eval(inputs) ;
    end
  end

  % Accumulate gradient.
  if strcmp(mode, 'train')
    if ~isempty(parserv), parserv.sync() ; end
    state = accumulateGradients(net, state, params, batchSize, parserv) ;
  end

  % Get statistics.
  time = toc(start) + adjustTime ;
  batchTime = time - stats.time ;
  stats.num = num ;
  stats.time = time ;
  stats = params.extractStatsFn(stats,net) ;
  currentSpeed = batchSize / batchTime ;
  averageSpeed = (t + batchSize - 1) / time ;
  if t == 3*params.batchSize + 1
    % compensate for the first three iterations, which are outliers
    adjustTime = 4*batchTime - time ;
    stats.time = time + adjustTime ;
  end

  fprintf(' %.1f (%.1f) Hz', averageSpeed, currentSpeed) ;
  for f = setdiff(fieldnames(stats)', {'num', 'time'})
    f = char(f) ;
    fprintf(' %s: %.3f', f, stats.(f)) ;
  end
  fprintf('\n') ;
end

% Save back to state.
state.stats.(mode) = stats ;
if params.profile
  if numGpus <= 1
    state.prof.(mode) = profile('info') ;
    profile off ;
  else
    state.prof.(mode) = mpiprofile('info');
    mpiprofile off ;
  end
end
if ~params.saveSolverState
  state.solverState = [] ;
else
  state.solverState = cellfun(@gather, state.solverState, 'uniformoutput', false) ;
end

net.reset() ;
net.move('cpu') ;

% -------------------------------------------------------------------------
function state = accumulateGradients(net, state, params, batchSize, parserv)
% -------------------------------------------------------------------------
numGpus = numel(params.gpus) ;
otherGpus = setdiff(1:numGpus, labindex) ;

for p=1:numel(net.params)

  if ~isempty(parserv)
    parDer = parserv.pullWithIndex(p) ;
  else
    parDer = net.params(p).der ;
  end

  switch net.params(p).trainMethod

    case 'average' % mainly for batch normalization
      thisLR = net.params(p).learningRate ;
      net.params(p).value = vl_taccum(...
          1 - thisLR, net.params(p).value, ...
          (thisLR/batchSize/net.params(p).fanout),  parDer) ;

    case 'gradient'
      thisDecay = params.weightDecay * net.params(p).weightDecay ;
      thisLR = params.learningRate * net.params(p).learningRate ;

      if isempty(params.solver)
        if isempty(state.solverState{p})
          state.solverState{p} = zeros(size(parDer), 'like', parDer);
        end

        state.solverState{p} = vl_taccum(...
          params.solverOpts.momentum,  state.solverState{p}, ...
          - (1 / batchSize), parDer) ;
        net.params(p).value = vl_taccum(...
          (1 - thisLR * thisDecay / (1 - params.solverOpts.momentum)),  ...
          net.params(p).value, ...
          thisLR, state.solverState{p}) ;
      else
        grad = (1 / batchSize) * parDer + thisDecay * net.params(p).value;
        % call solver function to update weights
        [net.params(p).value, state.solverState{p}] = ...
          params.solver(net.params(p).value, state.solverState{p}, ...
          grad, params.solverOpts, thisLR) ;
      end

    otherwise
      error('Unknown training method ''%s'' for parameter ''%s''.', ...
        net.params(p).trainMethod, ...
        net.params(p).name) ;
  end
end

% -------------------------------------------------------------------------
function stats = accumulateStats(stats_)
% -------------------------------------------------------------------------

for s = {'train', 'val'}
  s = char(s) ;
  total = 0 ;

  % initialize stats stucture with same fields and same order as
  % stats_{1}
  stats__ = stats_{1} ;
  names = fieldnames(stats__.(s))' ;
  values = zeros(1, numel(names)) ;
  fields = cat(1, names, num2cell(values)) ;
  stats.(s) = struct(fields{:}) ;

  for g = 1:numel(stats_)
    stats__ = stats_{g} ;
    num__ = stats__.(s).num ;
    total = total + num__ ;

    for f = setdiff(fieldnames(stats__.(s))', 'num')
      f = char(f) ;
      stats.(s).(f) = stats.(s).(f) + stats__.(s).(f) * num__ ;

      if g == numel(stats_)
        stats.(s).(f) = stats.(s).(f) / total ;
      end
    end
  end
  stats.(s).num = total ;
end

% -------------------------------------------------------------------------
function stats = extractStats(stats, net)
% -------------------------------------------------------------------------
sel = find(cellfun(@(x) isa(x,'dagnn.Loss'), {net.layers.block})) ;
for i = 1:numel(sel)
  stats.(net.layers(sel(i)).outputs{1}) = net.layers(sel(i)).block.average ;
end

% -------------------------------------------------------------------------
function saveState(fileName, net_, state)
% -------------------------------------------------------------------------
net = net_.saveobj() ;
save(fileName, 'net', 'state') ;

% -------------------------------------------------------------------------
function saveStats(fileName, stats)
% -------------------------------------------------------------------------
if exist(fileName)
  save(fileName, 'stats', '-append') ;
else
  save(fileName, 'stats') ;
end

% -------------------------------------------------------------------------
function [net, state, stats] = loadState(fileName)
% -------------------------------------------------------------------------
load(fileName, 'net', 'state', 'stats') ;
net = dagnn.DagNN.loadobj(net) ;
if isempty(whos('stats'))
  error('Epoch ''%s'' was only partially saved. Delete this file and try again.', ...
        fileName) ;
end

% -------------------------------------------------------------------------
function epoch = findLastCheckpoint(modelDir)
% -------------------------------------------------------------------------
list = dir(fullfile(modelDir, 'net-epoch-*.mat')) ;
tokens = regexp({list.name}, 'net-epoch-([\d]+).mat', 'tokens') ;
epoch = cellfun(@(x) sscanf(x{1}{1}, '%d'), tokens) ;
epoch = max([epoch 0]) ;

% -------------------------------------------------------------------------
function switchFigure(n)
% -------------------------------------------------------------------------
if get(0,'CurrentFigure') ~= n
  try
    set(0,'CurrentFigure',n) ;
  catch
    figure(n) ;
  end
end

% -------------------------------------------------------------------------
function clearMex()
% -------------------------------------------------------------------------
clear vl_tflow vl_imreadjpeg ;

% -------------------------------------------------------------------------
function prepareGPUs(opts, cold)
% -------------------------------------------------------------------------
numGpus = numel(opts.gpus) ;
if numGpus > 1
  % check parallel pool integrity as it could have timed out
  pool = gcp('nocreate') ;
  if ~isempty(pool) && pool.NumWorkers ~= numGpus
    delete(pool) ;
  end
  pool = gcp('nocreate') ;
  if isempty(pool)
    parpool('local', numGpus) ;
    cold = true ;
  end

end
if numGpus >= 1 && cold
  fprintf('%s: resetting GPU\n', mfilename)
  clearMex() ;
  if numGpus == 1
    gpuDevice(opts.gpus)
  else
    spmd
      clearMex() ;
      gpuDevice(opts.gpus(labindex))
    end
  end
end


function setup_vocpart()
%% download images
if(~exist('../data/VOC_part','dir'))
    system('wget -O ../VOCPart.tar.gz --no-check-certificate http://www.stat.ucla.edu/~xianjie.chen/pascal_part_dataset/trainval.tar.gz');
    mkdir('../data/VOC_part/')
    system('tar -xvzf ../VOCPart.tar.gz -C ../data/VOC_part/');
    system('rm ../VOCPart.tar.gz');
    system('wget -O ../img.tar http://host.robots.ox.ac.uk/pascal/VOC/voc2010/VOCtrainval_03-May-2010.tar');
    system('tar -xvf ../img.tar -C ../data/VOC_part/');
    system('rm ../img.tar');
end

%% settings
conf.data.catedir='../data/VOC_part/';
conf.data.imgdir='../data/VOC_part/VOCdevkit/VOC2010/JPEGImages/';
conf.data.readCode='./data_input/data_input_VOC/';

conf.data.minArea=50^2;

conf.output.dir='./mat/';

Name_batch={'bird','cat','cow','dog','horse','sheep'};
for i=1:numel(Name_batch)
    mkdir([conf.output.dir,Name_batch{i}]);
    save([conf.output.dir,Name_batch{i},'/conf.mat'],'conf');
end

addpath(genpath('./tool'));
addpath(conf.data.readCode);


function e2s2_storeSPGTOverlap(varargin)
% e2s2_storeSPGTOverlap(varargin)
%
% Augment the superpixel structure with the overlap with the GT blob.
%
% Copyright by Holger Caesar, 2015

% Parse input
p = inputParser;
addParameter(p, 'dataset', SiftFlowDatasetMC());
addParameter(p, 'projectName', 'WeaklySupervisedLearning');
addParameter(p, 'spName', 'Felzenszwalb2004-k100-sigma0.8-colorTypesRgb');
addParameter(p, 'gtName', 'GroundTruth');
parse(p, varargin{:});

dataset = p.Results.dataset;
projectName = p.Results.projectName;
spName = p.Results.spName;
gtName = p.Results.gtName;

% Create paths
global glFeaturesFolder;
segmentFolderSP = fullfile(glFeaturesFolder, projectName, dataset.name, 'segmentations', spName);
segmentFolderGT = fullfile(glFeaturesFolder, projectName, dataset.name, 'segmentations', gtName);

% Get image list
[imageList, imageCount] = dataset.getImageList(true);

for imageIdx = 1 : imageCount,
    printProgress(sprintf('Storing GT-SP (%s) overlap for image', spName), imageIdx, imageCount, 50);
    imageName = imageList{imageIdx};
    imageSize = dataset.getImageSize(imageName);

    % Get SP blobs
    segmentPathSP = fullfile(segmentFolderSP, [imageName, '.mat']);
    assert(exist(segmentPathSP, 'file') ~= 0);
    segmentStructSP = load(segmentPathSP, 'propBlobs');
    blobsSP = segmentStructSP.propBlobs;

    % Get GT blobs
    segmentPathGT = fullfile(segmentFolderGT, [imageName, '.mat']);
    assert(exist(segmentPathGT, 'file') ~= 0);
    segmentStructGT = load(segmentPathGT, 'propBlobs');
    blobsGT = segmentStructGT.propBlobs;

    % Compute overlap
    overlapRatiosSPGT = computeBlobOverlapSum(blobsSP, blobsGT, imageSize); %#ok<NASGU>

    % Store to disk (append)
    assert(exist(segmentPathSP, 'file') ~= 0);
    save(segmentPathSP, 'overlapRatiosSPGT', '-append');
end;


datasetPath='/home/bernard/HD1/ABC/sun';
addpath('..');
lambdas = 10.^[-3:3];
sigmas=10.^[-3:3];
tasks=[0];

validationClasses_generalscript(datasetPath, lambdas, sigmas, tasks);


function []=addLightButton(varargin)
%% Viewing figures: projecting light
% addLightButton
% addLightButton(hf)

% This script creates a new pushtool in a figure's toolbar to manipulate
% the light projected on a displayed axis
%%
switch nargin
    case 0
        hf=gcf;
    case 1
        hf=varargin{1};
end

% Get icon
filePath=mfilename('fullpath');
toolboxPath=fileparts(fileparts(filePath));
iconPath=fullfile(toolboxPath,'lib_ext','GIBBON','icons');
hb = findall(hf,'Type','uitoolbar');

D=imread(fullfile(iconPath,'lightbulb.jpg'));
S=double(D);
S=S-min(S(:));
S=S./max(S(:));
if size(S,3)==1
    S=repmat(S,[1 1 3]);
end

% Create a uipushtool in the toolbar
uipushtool(hb(1),'TooltipString','light','CData',S,'Tag','light_button','ClickedCallback',{@lightFunc,{hf}});

end

%% Light function  lightFunc

function lightFunc(~,~,inputCell)

hf = inputCell{1};
ha = findobj(hf,'type','axes');

if isempty(ha)
    msgbox('There are no axes in the figure');
else
    prompt = {'Light'};
    title = '';
    format = struct('type','list');
    format.style = 'popupmenu';
    format.items = {' -- Select a lighting option -- ','none','left','right','headlight'};
    default = cell(size(prompt,1),1);
    default{1,1} = 1; % Default selection will always be instruction item
    default = cell2struct(default,prompt,1);
    prompt = repmat(prompt,1,2);
    options.AlignControls = 'on';
    choice = inputsdlg(prompt,title,format,default,options);

    % Unless the user closes the pop up window, clear all existing light
    if choice.Light ~= 1
        existingLight = findobj(ha,'type','light');
        if ~isempty(existingLight)
            delete(existingLight);
        end
        % Apply selected light to all figure axes
        if choice.Light == 3
            for ia = 1:size(ha,1)
                axes(ha(ia)); % Set the current axis
                h(ia) = camlight('left');
            end
        elseif choice.Light == 4
            for ia = 1:size(ha,1)
                axes(ha(ia));
                h(ia) = camlight('right');
            end
        elseif choice.Light == 5
            for ia = 1:size(ha,1)
                axes(ha(ia));
                h(ia) = camlight('headlight');
            end
        end
    end
end
end

%%
% MultiDIC: a MATLAB Toolbox for Multi-View 3D Digital Image Correlation
%
% License: <https://github.com/MultiDIC/MultiDIC/blob/master/LICENSE.txt>
%
% Copyright (C) 2018  Dana Solav
%
% Modified by Rana Odabas 2018
%
% If you use the toolbox/function for your research, please cite our paper:
% <https://engrxiv.org/fv47e>


function dap=links2dap(links);
% LINKS2DAP extract OpenDAP Data URLs from OpenSearch links
% Usage: dap=links2dap(links);
%    [links,struc]=opensearch(q);
%    dap=links2dap(links);

% Rich Signell (rsignell@usgs.gov)
k=0;
dap=[];
for i=1:length(links)
    s=char(links{i});
    if ~isempty(regexpi(s,'dodsC')),
        k=k+1;
%        e=regexpi(s,'\.html');
%        dap{k}=s(1:e-1);
        dap{k}=s;
    end
end


%% Copyright (C) 2014-2016, 2019-2020, 2022 Colin B. Macdonald
%% Copyright (C) 2017 Mike Miller
%%
%% This file is part of OctSymPy.
%%
%% OctSymPy is free software; you can redistribute it and/or modify
%% it under the terms of the GNU General Public License as published
%% by the Free Software Foundation; either version 3 of the License,
%% or (at your option) any later version.
%%
%% This software is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty
%% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
%% the GNU General Public License for more details.
%%
%% You should have received a copy of the GNU General Public
%% License along with this software; see the file COPYING.
%% If not, see <http://www.gnu.org/licenses/>.

%% -*- texinfo -*-
%% @deftypefun {[@var{A}, @var{db}] =} python_ipc_driver (@dots{})
%% Private function: run Python/SymPy command and return objects.
%%
%% @var{A} is the resulting object, which might be an error code.
%%
%% @var{db} usually contains diagnostics to help with debugging
%% or error reporting.
%% @end deftypefun

function [A, db] = python_ipc_driver(what, cmd, varargin)

  which_ipc = sympref('ipc');

  %% version check
  if exist('OCTAVE_VERSION', 'builtin')
    if (compare_versions (OCTAVE_VERSION (), '5.1', '<'))
      fprintf(['\n********************************************************************\n' ...
               'Your Octave version is %s but Octsympy is currently untested on\n' ...
               'anything before 5.1.\n\n'], OCTAVE_VERSION ())
      warning('Old Octave version detected: probably trouble ahead!')
      fprintf('\n********************************************************************\n\n')
      fflush(stdout);
    end
  end

  if (strcmp(lower(which_ipc), 'default'))
    % TODO: may need to adjust, ideally just 'py'
    if (exist ('pyversion') && exist ('pyexec') && exist ('pyeval'))
      which_ipc = 'native';
    elseif (exist ('popen2') > 1)
      which_ipc = 'popen2';
    else
      which_ipc = 'system';
    end
  end

  switch lower(which_ipc)
    case 'native'
      [A, db] = python_ipc_native(what, cmd, varargin{:});

    case 'popen2'
      [A, db] = python_ipc_popen2(what, cmd, varargin{:});

    case 'system'
      if (ispc () && (~isunix ()))
        [A, db] = python_ipc_sysoneline(what, cmd, varargin{:});
      else
        [A, db] = python_ipc_system(what, cmd, false, varargin{:});
      end

    case 'systmpfile'
      %% for debugging, not intended for long-term usage
      [A, db] = python_ipc_system(what, cmd, true, varargin{:});

    case 'sysoneline'
      %% for debugging, not intended for long-term usage
      [A, db] = python_ipc_sysoneline(what, cmd, varargin{:});

    otherwise
      if (strcmp (what, 'reset'))
        A = true;
        db = [];
      else
        error ('invalid ipc mechanism')
      end
  end


function [HDR]=sseek(HDR,offset,origin)
% SSEEK repositions file position indicator
%  HDR = sseek(HDR,offset,origin)
%
%  offset       number of samples relative to origin
%  origin
%        -1,'bof':   begin of file
%         0,'cof':   current file position
%        +1,'eof':   end of file
%
% See also: SOPEN, SREAD, SWRITE, SCLOSE, SSEEK, SREWIND, STELL, SEOF

%	$Id: sseek.m 2205 2009-10-27 12:18:15Z schloegl $
%	(C) 1997-2005,2006,2007 by Alois Schloegl <a.schloegl@ieee.org>
%    	This is part of the BIOSIG-toolbox http://biosig.sf.net/

% This program is free software; you can redistribute it and/or
% modify it under the terms of the GNU General Public License
% as published by the Free Software Foundation; either version 2
% of the  License, or (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

if strcmp(origin,'bof')
	origin = -1;
elseif strcmp(origin,'cof')
	origin = 0;
elseif strcmp(origin,'eof')
	origin = 1;
end;

if origin == -1,
        HDR.FILE.POS = offset;
        if strmatch(HDR.TYPE,{'ACQ','BDF','EDF','GDF','EPL','MFER','SCP','native','TMS32','WG1'}),
	elseif HDR.FILE.FID>2,
                POS = HDR.HeadLen+HDR.AS.bpb*offset;
                if POS~=ceil(POS),  % for alpha format
                        fprintf(HDR.FILE.stderr,'Error STELL (alpha): starting position is non-integer\n');
                        return;
                end
                HDR.FILE.status = fseek(HDR.FILE.FID,POS,-1);
        end

elseif origin == 0,
        HDR.FILE.POS = HDR.FILE.POS + offset;
        if strmatch(HDR.TYPE,{'ACQ','BDF','EDF','GDF','EPL','MFER','SCP','native','TMS32','WG1'}),
	elseif HDR.FILE.FID>2,
                POS = HDR.AS.bpb*offset;
                if POS~=ceil(POS),  % for alpha format
                        fprintf(HDR.FILE.stderr,'Error STELL (alpha): starting position is non-integer\n');
                        return;
                end
                HDR.FILE.status = fseek(HDR.FILE.FID,POS,0);
        end

elseif origin == 1,
	if 0, %strmatch(HDR.TYPE,{}),
		HDR.FILE.POS = HDR.NRec+offset;
		HDR.FILE.status = fseek(HDR.FILE.FID,HDR.AS.bpb*offset,1);
	elseif strmatch(HDR.TYPE,{'ACQ','BDF','EDF','GDF','EPL','Sigma'}),
		HDR.FILE.POS = HDR.NRec*HDR.SPR+offset;
                if HDR.FILE.POS < 0,
                        HDR.FILE.POS = 0;
                elseif HDR.FILE.POS > HDR.NRec*HDR.SPR,
                        HDR.FILE.POS = HDR.NRec*HDR.SPR;
                end;
		HDR.FILE.status = fseek(HDR.FILE.FID,HDR.HeadLen+HDR.FILE.POS*HDR.AS.bpb,-1);
	elseif strmatch(HDR.TYPE,{'CTF','Nicolet'}),
		POS = HDR.AS.endpos+offset*HDR.AS.bpb;
		HDR.FILE.status = fseek(HDR.FILE.FID,POS,-1);
		HDR.FILE.POS = (POS-HDR.HeadLen)/HDR.AS.bpb;
	elseif strmatch(HDR.TYPE,{'AINF','BKR','ET-MEG','ISHNE','RG64','MIT','LABVIEW','SMA','BVbinmul','BCI2000'}),
		HDR.FILE.POS = HDR.AS.endpos+offset;
		HDR.FILE.status = fseek(HDR.FILE.FID,HDR.AS.bpb*offset,1);
	elseif strmatch(HDR.TYPE,{'CNT','EEG','AVG','EGI','SND','WAV','AIF','CFWB','DEMG'}),
		HDR.FILE.POS = HDR.AS.endpos+offset;
		HDR.FILE.status = fseek(HDR.FILE.FID,HDR.HeadLen+(HDR.AS.endpos+offset)*HDR.AS.bpb,-1);
        elseif strmatch(HDR.TYPE,{'alpha'}),
                POS = HDR.HeadLen+(HDR.AS.endpos+offset)*HDR.AS.bpb;
                if POS~=ceil(POS),  % for alpha format
                        fprintf(HDR.FILE.stderr,'Error STELL (alpha): starting position is non-integer\n');
                        return;
                end
		HDR.FILE.POS = HDR.AS.endpos+offset;
		HDR.FILE.status = fseek(HDR.FILE.FID,POS,-1);
        elseif strmatch(HDR.TYPE,{'RDF','SIGIF'}),
		HDR.FILE.POS = length(HDR.Block.Pos)+offset;
        elseif strmatch(HDR.TYPE,{'BVascii','BVbinvec','EEProbe-CNT','EEProbe-AVR','FIF','native','MFER','SCP','TMS32','WG1'}),
		HDR.FILE.POS = HDR.AS.endpos+offset;
	else
		fprintf(HDR.FILE.stderr,'Warning SSEEK: format %s not supported.\n',HDR.TYPE);
	end;
else
        fprintf(2,'error SSEEK: 3rd argument "%s" invalid\n',origin);
        return;
end;


function [cnmfAnalysisOutput] = computeCnmfSignalExtractionOriginal(inputMovie,numExpectedComponents,varargin)
	% Wrapper for CNMF, for use with https://github.com/epnev/ca_source_extraction/commit/8799b13df2b09f30e27fc852e4f5f39ae6f44405
	% Building off of demo_script.m in CNMF github repo
	% Biafra Ahanonu
	% started: 2016.01.20
	% inputs
		% inputMovie - a string or a cell array of strings pointing to the movies to be analyzed (recommended). Else, [x y t] matrix where t = frames.
		% numExpectedComponents - number of expected components
	% outputs
		% cnmfAnalysisOutput - structure containing extractedImages and extractedSignals along with input parameters to the algorithm
	% READ BEFORE RUNNING
		% Get CVX from http://cvxr.com/cvx/doc/install.html
		% Run the below commands in Matlab after unzipping
		% cvx_setup
		% cvx_save_prefs (permanently stores settings)

	[cnmfAnalysisOutput] = ciapkg.signal_extraction.computeCnmfSignalExtractionOriginal(inputMovie,numExpectedComponents,'passArgs', varargin);
end


report_this_filefun(mfilename('fullpath'));

di = km2deg(red(:,7));
az = red(:,8);
[la,lo] =reckon(az*0+r(2),az*0+r(1),di,az);
s = [lo la red(:,4) red(:,5) red(:,3)-red(:,2) red(:,6)];
cd /Seis/obelix/stefan/DEM
save redaz.dat s -ascii


%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% /**
%  * Copyright (C) 2016 CoDyCo
%  * @author: Daniele Pucci, Gabriele Nava
%  * Permission is granted to copy, distribute, and/or modify this program
%  * under the terms of the GNU General Public License, version 2 or any
%  * later version published by the Free Software Foundation.
%  *
%  * A copy of the license can be found at
%  * http://www.robotcub.org/icub/license/gpl.txt
%  *
%  * This program is distributed in the hope that it will be useful, but
%  * WITHOUT ANY WARRANTY; without even the implied warranty of
%  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
%  * Public License for more details
%  */
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% NOTE: THIS SCRIPT IS RUN AUTOMATICALLY WHEN THE USER STARTS THE ASSOCIATED
% SIMULINK MODEL. NO NEED TO RUN THIS SCRIPT EVERY TIME.
clearvars -except sl_synch_handles simulinkStaticGUI
clc

% Add path to local source code
addpath('./src/')

%% GENERAL SIMULATION INFO
%
% If you are simulating the robot with Gazebo, remember that it is required
% to launch Gazebo as follows:
%
%     gazebo -slibgazebo_yarp_clock.so
%
% and properly set the environmental variable YARP_ROBOT_NAME in the .bashrc.

% Simulation time in seconds. For long simulations, put an high number
% (not inf) for allowing automatic code generation
Config.SIMULATION_TIME = 600000;

% Controller period [s]
Config.tStep           = 0.01;

%% PRELIMINARY CONFIGURATION
%
% DEMO_TYPE: defines the kind of demo that will be performed.
%
% 'YOGA': the robot will perform the YOGA++ demo (highly dynamic movements
%         while balancing on one foot and two feet)
%
% 'COORDINATOR': the robot can either balance on two feet or move from left
%                to right follwing a desired center-of-mass trajectory.
%
DEMO_TYPE                     = 'YOGA';

% Config.SCOPES: debugging scopes activation
Config.SCOPES_WRENCHES        = true;
Config.SCOPES_GAIN_SCHE_INFO  = true;
Config.SCOPES_MAIN            = true;
Config.SCOPES_QP              = true;

% DATA PROCESSING
%
% Save the Matlab workspace after stopping the simulation
Config.SAVE_WORKSPACE         = false;

% Verify that the integration time has been respected during the simulation
Config.CHECK_INTEGRATION_TIME = true;
Config.PLOT_INTEGRATION_TIME  = false;

% Run robot-specific configuration parameters
run(strcat('app/robots/',getenv('YARP_ROBOT_NAME'),'/configRobot.m'));
run(strcat('app/robots/',getenv('YARP_ROBOT_NAME'),'/configStateMachine.m'));
run(strcat('app/robots/',getenv('YARP_ROBOT_NAME'),'/gainsAndReferences.m'));

% Deactivate/activate the internal coordinator
if strcmpi(DEMO_TYPE, 'COORDINATOR')

    Config.COORDINATOR_DEMO = true;

elseif strcmpi(DEMO_TYPE, 'YOGA')

    Config.COORDINATOR_DEMO = false;
end


function [bbox3M, planC] = crop_for_larynx(planC,paramS,varargin)
% Custom crop function for larynx segmentation model
% AI 10/04/19

indexS = planC{end};
strC = {planC{indexS.structures}.structureName};
bboxIdx = [];

%% Return bounding box if it exists
if isfield(paramS,'saveStrToPlanCFlag') && paramS.saveStrToPlanCFlag
    if isfield(paramS,'outStrName')
        outStrName = paramS.outStrName;
    else
        outStrName = 'crop_for_larynx';
    end
    bboxIdx = getMatchingIndex(outStrName,strC,'EXACT');
end
if ~isempty(bboxIdx)
    bbox3M = getStrMask(bboxIdx,planC);
else
    %% Create union of masseters (left & right) and medial pterygoids (left & right)
    unionStrListC = paramS.structureName.chewingStructures;

    for k = 1:length(unionStrListC)
        idx = getMatchingIndex(unionStrListC{k},strC,'EXACT');
        if k==1
            scanIdx = getStructureAssociatedScan(idx,planC);
            sizV = size(getScanArray(scanIdx,planC));
            mask3M = false(sizV);
        end
        [strMask3M, planC] = getStrMask(idx,planC);
        mask3M = mask3M | strMask3M;
    end

    %Get limits of bbox around union str
    %mask3M = getStrMask(endStr,planC);
    if sum(mask3M(:))>1
        [minr,~,minc,maxc,mins,~] = compute_boundingbox(mask3M);
    else
        minr = 1;
        minc = 1;
        maxc = size(mask3M,2);
        mins = 1;
    end

    %% Get limits of bounding box around cropped pt outline
    outStrName = paramS.structureName.cropStructure;
    idx = getMatchingIndex(outStrName,strC,'EXACT');
    cropMask3M = getStrMask(idx,planC);
    [~,maxr,~,~,~,maxs] = compute_boundingbox(cropMask3M);

    %Get final bounding box
    bbox3M = false(size(mask3M));
    bbox3M(minr:maxr,minc:maxc,mins:maxs) = true;
end

end


function headSizeAll = getHeadSizeAll(annolist)
headSizeAll = nan(length(annolist),1);
for imgidx = 1:length(annolist)
    rect = annolist(imgidx).annorect;
    headSizeAll(imgidx) =  util_get_head_size(rect);
end
end


function sl_customization(cm)
% Customizes Simulink context menu with all blocks from a model file
% custom_context_menu_blocks.mdl file. These blocks are then accessible
% through context menu: Add custom block / List of blocks from library.
% The chosen block is added at the position of mouse context menu click.
%
% Please feel free to modify custom_context_menu_blocks.mdl to meet your
% expectations.
%
% OUTPUTS:  Customised Simulink context
%
% Author: Paul Proteus (e-mail: proteus.paul (at) yahoo (dot) com)
% Version: 1.0
% Changes tracker:  31.01.2011  - First version
%
% Note:  It might be neccessery to run sl_refresh_customizations to refresh
%        Simulink context menu or set the Matlab path correctly.
%
% Inspired by and parts of code taken from:
%   1. Alex - Add Simulink Commonly Used Blocks with context menu (#22067)
%   2. Giacomo Faggiani - Create From Blocks (#25736)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Register custom menu function.
cm.addCustomMenuFcn('Simulink:PreContextMenu', @getMyMenuItems);
end

%% Define the custom menu function.
function schemaFcns = getMyMenuItems(callbackInfo)
  schemaFcns = {@addSimulinkBlock};
end

%% Define the schema function for first menu item.
function schema = addSimulinkBlock(callbackInfo)
  schema = sl_container_schema;
  schema.label  = 'Add custom block';
  % Get mouse position
  mousePosition = get(0,'PointerLocation');
  % Get available block from the library
  customMDL = 'custom_context_menu_blocks';
  load_system(customMDL);
  availableBlocks = find_system(customMDL,'SearchDepth',1);
  for iBlock=2:length(availableBlocks),
     blockName = availableBlocks{iBlock};
     blockName = blockName(max(strfind(blockName,'/'))+1:end);
     childFunc(iBlock-1) = {{@addLibraryBlock,{customMDL,blockName,mousePosition}}};
  end
  schema.childrenFcns = childFunc;
end

function schema = addLibraryBlock(callbackInfo)
  schema = sl_action_schema;
  schema.label = callbackInfo.userdata{2};
  schema.userdata = callbackInfo.userdata;
  schema.callback = @slAddLibraryBlock;
end

% SUB-FUNCTIONS
function slAddLibraryBlock(inArgs)

% Define initial information
modelName     = gcs;
customMDL     = inArgs.Userdata{1};
blockName     = inArgs.Userdata{2};
mousePosition = inArgs.Userdata{3};

% Source and destination path
dstStr = [modelName '/' blockName];
srcStr = [customMDL '/' blockName];

% Get more information for position calculation
blockSizeRef = get_param(srcStr, 'Position');
locationBase = get_param(modelName,'Location');
scrollOffset = get_param(modelName,'ScrollbarOffset');
screenSize   = get(0,'ScreenSize');

% Calculate new position
p_X = mousePosition(1) - locationBase(1) + scrollOffset(1);
p_Y = screenSize(4) - mousePosition(2) - locationBase(2) + scrollOffset(2) ;
width = blockSizeRef(3) - blockSizeRef(1);
height = blockSizeRef(4) - blockSizeRef(2);
location = [p_X p_Y p_X+width p_Y+height];

% Add block
block = add_block(srcStr, dstStr, 'MakeNameUnique', 'on');
set(block, 'Position', location);

close_system(customMDL);

end


classdef TestThinning
    %TestThinning

    methods (Static)
        function test_1
            bw = cv.imread(fullfile(mexopencv.root(),'test','bw.png'), ...
                'Grayscale',true, 'ReduceScale',2);
            out = cv.thinning(bw, 'ThinningType','ZhangSuen');
            validateattributes(out, {class(bw)}, {'size',size(bw)});
        end

        function test_error_argnum
            try
                cv.thinning();
                throw('UnitTest:Fail');
            catch e
                assert(strcmp(e.identifier,'mexopencv:error'));
            end
        end
    end

end