1function viewedf(Action, ActOption) 2% viewedf 3% Display EDF (European Data Format) files 4% This program requires Matlab Version >= 5.2 and should work with Matlab 6.x 5% 6% Command line functionality (note: all commands are case sensitive): 7% viewedf : start program 8% viewedf('OpenEDFFile', FILENAME) : open FILENAME 9% viewedf('Goto', RECORD) : move to RECORD 10% viewedf('GotoSecond', SECOND) : move to a certain SECOND 11% viewedf('Prev') : move back one screen 12% viewedf('Next') : move forward one screen 13% viewedf('PrevFast') : move back 5 screens 14% viewedf('NextFast') : move forward 5 screens 15% viewedf('Close') : close viewer 16% 17% Keyboard shortcuts: 18% '+' : move to next screen 19% '-' : move to previous screen 20% 'U' : scale all channels up 21% 'D' : scale all channels down 22% 23% Version 3.04Alpha, 10/22/01 24% (c) Herbert Ramoser (herbert.ramoser@arcs.ac.at) 25% 26% This Software is subject to the GNU public license v2 or later. 27 28% $Id: sopen.m 2529 2010-09-06 23:32:46Z schloegl $ 29% This is part of the BIOSIG-toolbox http://biosig.sf.net/ 30% 31% BioSig is free software: you can redistribute it and/or modify 32% it under the terms of the GNU General Public License as published by 33% the Free Software Foundation, either version 2 of the License, or 34% (at your option) any later version. 35% 36% BioSig is distributed in the hope that it will be useful, 37% but WITHOUT ANY WARRANTY; without even the implied warranty of 38% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 39% GNU General Public License for more details. 40% 41% You should have received a copy of the GNU General Public License 42% along with BioSig. If not, see <http://www.gnu.org/licenses/>. 43 44 45% Changes: 46% 01/27/98 Ramoser: Plugins may replace EDF data, optional parameter string 47% is passed to the plugin 48% 01/30/98 Ramoser: plotting of EDF.Valid information 49% 02/02/98 Ramoser: print option added 50% 02/18/98 Ramoser: Stairplot-feature added, bug for hypnograms removed 51% 06/16/98 Ramoser: bugs of Matlab 5.2 fixed (return, inputdlg) 52% display multiple EDF files 53% fixed order of channels 54% export of matrices to workspace 55% increase in plotting speed 56% 09/18/98 Ramoser: new EDF open and read functions included 57% upside down display of plots 58% use of cell arrays to store EDF data 59% data passed to plugins has changed 60% 11/01/98 Woertz: reset display after calls of plugin menus 61% 11/23/98 Ramoser: give only one file to plugin 62% handling of plugins when EDF files are closed 63% 11/30/98 Ramoser: GDF functionality added 64% 12/02/98 Ramoser: optionally display plot Y tick-labels 65% 12/03/98 Ramoser: fixed dialog boxes under X (drawnow added) 66% upside-down plotting bug removed 67% 12/07/98 Ramoser: scaling buttons added 68% 12/09/98 Ramoser: physical dimension added to Y-label 69% 02/18/99 Ramoser: problems with multiple files, multiple record lengths 70% and scrollbar removed 71% 03/04/99 Ramoser: Assign matrix - plugin bug removed 72% 03/26/99 Ramoser: GDF 0.12 added, set properties of all channels 73% simultaneusly ('Apply to all' button) 74% 03/31/99 Ramoser: time tracking line added 75% 04/01/99 Ramoser: print problems resolved 76% 04/29/99 Ramoser: do not reset display properties after a call to 77% plugin-menu 78% 05/04/99 Ramoser: time tracking line bugs removed 79% 05/12/99 Ramoser: file positioning information added (EDFHead.AS.startrec 80% & numrec) 81% 03/17/00 Ramoser: add command line functionality, add 'Goto second' 82% 10/22/01 Ramoser: some updates for Matlab 6 83% 01 Sep 2008 Schloegl: use sopen, sclose 84% Jun 2010 Alois Schloegl 85 86FastPageIncrement = 5; 87PageIncrement = 1; 88warning('off'); 89 90switch nargin, 91 case 0, 92 if ~isempty(findobj('Tag', 'ViewEDFFigure')) 93 error('Only one copy of VIEWEDF may be run'); 94 end 95 LocalInitWindow; 96 case 1, 97 switch Action 98 case 'OpenEDFFile', 99 LocalEDFOpen; 100 case 'CloseEDFFile', 101 LocalEDFClose; 102 case 'Repaint' 103 LocalRepaint; 104 case 'AddPlugin' 105 LocalAddPlugin; 106 case 'RemovePlugin' 107 LocalRemovePlugin; 108 case 'PluginMenu' 109 LocalPluginMenu; 110 case 'PrevFast' 111 LocalChangeRecord(-FastPageIncrement,0); 112 case 'Prev' 113 LocalChangeRecord(-PageIncrement,0); 114 case 'NextFast' 115 LocalChangeRecord(FastPageIncrement,0); 116 case 'Next' 117 LocalChangeRecord(PageIncrement,0); 118 case 'HScroll' 119 LocalHScroll; 120 case 'ToggleUpdatePlugin' 121 LocalToggleUpdatePlugin; 122 case 'ToggleShowRange' 123 LocalToggleShowRange; 124 case 'ToggleShowCursor' 125 LocalToggleShowCursor; 126 case 'RecordProp' 127 LocalRecordProp; 128 case 'Goto' 129 LocalGotoRecord; 130 case 'GotoSecond' 131 LocalGotoSecond; 132 case 'Records' 133 LocalNumRecords; 134 case 'FileInfo' 135 LocalFileInfo; 136 case 'Channels' 137 LocalSelectChannels; 138 case 'About' 139 LocalAbout; 140 case 'Help' 141 LocalHelp; 142 case 'KeyPress' 143 LocalKeyPress; 144 case 'Print' 145 LocalPrint; 146 case 'AssignMat' 147 LocalAssignMat; 148 case 'ScaleUp' 149 LocalRescale('up'); 150 case 'ScaleDown' 151 LocalRescale('down'); 152 case 'Close' 153 LocalCloseViewEDF; 154 otherwise 155 error('VIEWEDF must be called without parameters'); 156 end 157 case 2, 158 switch Action 159 case 'OpenEDFFile', 160 LocalEDFOpen(ActOption); 161 case 'FileInfo' 162 LocalFileInfo(ActOption); 163 case 'Channels' 164 LocalSelectChannels(ActOption); 165 case 'MoveCursor' 166 LocalMoveCursor(ActOption); 167 case 'Goto' 168 LocalGotoRecord(ActOption); 169 case 'GotoSecond' 170 LocalGotoSecond(ActOption); 171 otherwise 172 error('Unknown argument!'); 173 end 174 otherwise 175 error('Unknown argument!'); 176end 177 178%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 179% LocalInitWindow 180% initializes the window (display buttons, ...) 181function LocalInitWindow() 182 183args = { 'NumberTitle', 'off', ... 184 'CloseRequestFcn', 'viewedf Close', ... 185 'IntegerHandle', 'off', ... 186 'KeyPressFcn', 'viewedf KeyPress', ... 187 'MenuBar', 'none', ... 188 'Color', [0.9, 0.9, 0.9], ... 189 'ResizeFcn', 'viewedf Repaint', ... 190 'Tag', 'ViewEDFFigure', ... 191 'Name', 'EDF File Viewer - (C) 1998-2001 DPMI, 2008 HCI, Graz University of Technology; 2010 Alois Schloegl' 192 }; 193if ~exist('OCTAVE_VERSION','builtin') 194 args = {args{:}, ... 195 'Units', 'Normalized', ... 196 'PaperPositionMode', 'Auto', ... 197 'PaperType', 'A4', ... 198 'PaperUnits', 'Normalized', ... 199 }; 200end; 201 202fig=figure(args{:}); 203 204Data=get(fig,'UserData'); 205 206% Menus 207mh = uimenu('Label', '&File'); 208uimenu(mh, ... 209 'Label', '&Open EDF', ... 210 'Callback', 'viewedf OpenEDFFile'); 211uimenu(mh, ... 212 'Label', '&Close EDF', ... 213 'Callback', 'viewedf CloseEDFFile'); 214uimenu(mh, ... 215 'Label', '&Add Plugin', ... 216 'Callback', 'viewedf AddPlugin'); 217uimenu(mh, ... 218 'Label', '&Remove Plugin', ... 219 'Callback', 'viewedf RemovePlugin'); 220uimenu(mh, ... 221 'Label', '&Print', ... 222 'Separator', 'on', ... 223 'Callback', 'viewedf Print'); 224uimenu(mh, ... 225 'Label', 'Assign &Matrix', ... 226 'Callback', 'viewedf AssignMat'); 227uimenu(mh, ... 228 'Label', 'E&xit', ... 229 'Separator', 'on', ... 230 'Callback', 'viewedf Close'); 231 232mh = uimenu('Label', '&Display'); 233uimenu(mh, ... 234 'Label', 'File &info', ... 235 'Callback', 'viewedf FileInfo'); 236uimenu(mh, ... 237 'Label', '&Goto Record', ... 238 'Callback', 'viewedf Goto'); 239uimenu(mh, ... 240 'Label', '&Goto Second', ... 241 'Callback', 'viewedf GotoSecond'); 242uimenu(mh, ... 243 'Label', '&Records on Screen', ... 244 'Callback', 'viewedf Records'); 245uimenu(mh, ... 246 'Label', '&Channels', ... 247 'Callback', 'viewedf Channels'); 248 249mh = uimenu('Label', '&Options'); 250uimenu(mh, ... 251 'Label', '&Update Plugin', ... 252 'Checked', 'on', ... 253 'Callback', 'viewedf ToggleUpdatePlugin'); 254uimenu(mh, ... 255 'Label', 'Show &Range', ... 256 'Checked', 'off', ... 257 'Callback', 'viewedf ToggleShowRange'); 258uimenu(mh, ... 259 'Label', 'Show &Cursor', ... 260 'Checked', 'off', ... 261 'Callback', 'viewedf ToggleShowCursor'); 262Data.Display.PluginMenu.Main = uimenu(mh, ... 263 'Label', '&Plugin'); 264 265mh = uimenu('Label', '&?'); 266uimenu(mh, ... 267 'Label', '&Help', ... 268 'CallBack', 'viewedf Help'); 269uimenu(mh, ... 270 'Label', '&About', ... 271 'CallBack', 'viewedf About'); 272 273% Strings 274textx = 0.02; 275textheight = LocalGetFontHeight(); 276texty = 1 - textheight / 4; 277Data.Display.Strings.CurrTime = uicontrol(fig, ... % Time string 278 'Style', 'Text', ... 279 'Units', 'Normalized', ... 280 'String', '', ... 281 'HorizontalAlignment', 'left', ... 282 'FontUnits', 'normalized', ... 283 'Position', [textx, texty - textheight, 0.2, ... 284 textheight]); 285Data.Display.Strings.TotTime = uicontrol(fig, ... % Total time string 286 'Style', 'Text', ... 287 'Units', 'Normalized', ... 288 'String', 'Total length : ', ... 289 'HorizontalAlignment', 'left', ... 290 'Position', [textx, texty - textheight, 0.2, ... 291 textheight]); 292Data.Display.Strings.DispTime = uicontrol(fig, ... % Displayed time stretch string 293 'Style', 'Text', ... 294 'Units', 'Normalized', ... 295 'String', 'Displayed : ', ... 296 'HorizontalAlignment', 'left', ... 297 'Position', [textx + 0.22, texty - textheight, 0.2, ... 298 textheight]); 299Data.Display.Strings.FileName = uicontrol(fig, ... % File string 300 'Style', 'Text', ... 301 'Units', 'Normalized', ... 302 'String', 'File : ', ... 303 'HorizontalAlignment', 'left', ... 304 'Position', [textx + 0.44, texty - textheight, 0.2, ... 305 textheight]); 306Data.Display.Strings.NumString = 4; 307 308% Build data structure 309% settings for the display (where to plot things, ...) 310Data.Display.Axes = []; % nothing to display 311Data.Display.YSpacing = 0.0025; % spacing between plots 312Data.EDF = []; 313Data.Plugin = []; 314Data.UpdatePlugin = 1; 315Data.ShowRange = 0; 316Data.ShowCursor = 0; 317Data.Display.Cursor = []; 318set(fig,'UserData',Data); 319drawnow; 320 321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 322% LocalResetDisplay 323% reset display variables 324function LocalResetDisplay() 325Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 326if length(Data.EDF)==0 327 return; 328end 329%EDF data 330MaxDur = max(LocalGetEDFInfo('Dur', Data.EDF)); 331for i=1:length(Data.EDF) 332 Data.Display.EDF(i).ShowRecords = [0, round(MaxDur / Data.EDF(i).Head.Dur)]; 333 [Data.EDF(i).Record, Data.EDF(i).Head] = ... 334 LocalEDFRead(Data.EDF(i).Head, Data.Display.EDF(i).ShowRecords); 335 Data.Display.EDF(i).ShowSignals = 1:Data.EDF(i).Head.NS; 336 Data.Display.EDF(i).DisplayMin = Data.EDF(i).Head.PhysMin; 337 Data.Display.EDF(i).DisplayMax = Data.EDF(i).Head.PhysMax; 338 Data.Display.EDF(i).StairPlot = zeros(1, Data.EDF(i).Head.NS); 339 Data.Display.EDF(i).UpDownPlot = Data.EDF(i).Head.PhysMin>Data.EDF(i).Head.PhysMax; %zeros(1, Data.EDF(i).Head.NS); 340end 341 342% Plugin data 343for i = 1:length(Data.Plugin) 344 [Data.Plugin(i).EDF, Data.Plugin(i).UserData] = ... 345 feval(Data.Plugin(i).Name, Data.EDF(1), Data.Plugin(i).UserData, ... 346 'Reset'); 347 Data.Display.Plugin(i).ShowRecords = [0, round(MaxDur / Data.Plugin(i).Head.Dur)]; 348 Data.Display.Plugin(i).ShowSignals = 1:Data.Plugin(i).Head.NS; 349 Data.Display.Plugin(i).DisplayMin = Data.Plugin(i).EDF.Head.PhysMin; 350 Data.Display.Plugin(i).DisplayMax = ... 351 Data.Plugin(i).EDF.Head.PhysMax; 352 Data.Display.Plugin(i).StairPlot = zeros(1, Data.Plugin(i).Head.NS); 353 Data.Display.Plugin(i).UpDownPlot = Data.EDF(i).Head.PhysMin>Data.EDF(i).Head.PhysMax; %zeros(1, Data.Plugin(i).Head.NS); 354end 355 356% update all strings 357tsec = max(LocalGetEDFInfo('FileDur', Data.EDF)); 358tmin = floor(tsec/60); 359tsec = rem(tsec,60); 360th = floor(tmin/60); 361tmin = rem(tmin,60); 362set(Data.Display.Strings.TotTime, 'String', ... 363 sprintf('Total length : %02d:%02d:%02d', th,tmin,tsec)); 364fname = 'File : '; 365% add '+' for additional files 366for i = 1:(length(Data.EDF) - 1) 367 fname = [fname Data.EDF(i).Head.FILE.Name '.' Data.EDF(i).Head.FILE.Ext ... 368 ' + ']; 369end 370fname = [fname Data.EDF(end).Head.FILE.Name '.' Data.EDF(end).Head.FILE.Ext]; 371set(Data.Display.Strings.FileName, 'String', fname); 372set(findobj('Tag', 'ViewEDFFigure'), 'UserData', Data); 373LocalRepaint(0); 374 375%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 376% LocalRepaint 377% initializes the window (display buttons, ...) 378function LocalRepaint(KeepOldPlots) 379figure(findobj('Tag', 'ViewEDFFigure')); 380Data = get(gcf, 'UserData'); 381fhght = LocalGetFontHeight; 382if length(Data.EDF)==0 383 return; 384end 385if nargin < 1 386 KeepOldPlots = 0; 387end 388KeepOldPlots = (KeepOldPlots ~= 0); 389 390% set display size (area left for plots) 391Data.Display.DrawRect = [0.005 1.5*fhght 0.85 1-1.5*fhght]; 392 393% get width of figure 394unit = get(gcf, 'Units'); 395set(gcf, 'Units', 'Pixels'); 396xpix = get(gcf, 'Position'); 397set(gcf, 'Units', unit); 398xpix = xpix(3); 399 400% calculate total number of plots 401TotPlots = 0; 402for i=1:length(Data.EDF) 403 TotPlots = TotPlots + length(Data.Display.EDF(i).ShowSignals); 404end 405for i=1:length(Data.Plugin) 406 TotPlots = TotPlots + length(Data.Display.Plugin(i).ShowSignals); 407end 408 409% update plugin-data 410LocalWatchOn; 411if Data.UpdatePlugin || ~KeepOldPlots, 412 for i = 1:length(Data.Plugin) 413 [Data.Plugin(i).EDF, Data.Plugin(i).UserData] = ... 414 feval(Data.Plugin(i).Name, Data.EDF(Data.Plugin(i).EDFFile), ... 415 Data.Plugin(i).UserData); 416 end 417end 418LocalWatchOff; 419 420Opt.YSpace = Data.Display.YSpacing; 421Opt.TxtHeight = fhght; 422Opt.TextWidth = 1 - Data.Display.DrawRect(3) - Data.Display.DrawRect(1) - ... 423 0.01; 424Opt.TextX = Data.Display.DrawRect(1) + Data.Display.DrawRect(3) + 0.005; 425Opt.ButHeight = Opt.TxtHeight * 1.2; 426Opt.ValidHeight = 0.005; 427Opt.FigX = Data.Display.DrawRect(1); 428Opt.FigWidth = Data.Display.DrawRect(3); 429if Data.ShowRange 430 Opt.LabelWidth = min([0.1, 4*LocalGetFontWidth]); 431else 432 Opt.LabelWidth = 0; 433end 434Opt.FigY = Data.Display.DrawRect(2) + Data.Display.DrawRect(4) - ... 435 1.5*Opt.TxtHeight - Opt.ValidHeight; 436Opt.FigHeight = (Data.Display.DrawRect(4) - 1.5*Opt.TxtHeight - ... 437 Opt.ValidHeight) / TotPlots - Opt.YSpace; 438Opt.TxtHeight = min([(Opt.FigHeight-Opt.YSpace)/2, Opt.TxtHeight]); 439Opt.ButHeight = min([(Opt.FigHeight-Opt.YSpace)/2, Opt.ButHeight]); 440Opt.XPixels = 4*xpix; 441Opt.ShowRange = Data.ShowRange; 442 443% clear old buttons and labels 444if ~KeepOldPlots && ~isempty(Data.Display.Axes), 445 delete(Data.Display.HScrollBar); 446 if ~isempty(Data.Display.Cursor); 447 delete(Data.Display.Cursor.Line(:)); 448 delete(Data.Display.Cursor.Menu.Text); 449 delete(Data.Display.Cursor.Menu.Menu); 450 Data.Display.Cursor = []; 451 end 452 delete(Data.Display.Axes(:).RecButton); 453 delete(Data.Display.Axes(:).ScaleUpButton); 454 delete(Data.Display.Axes(:).ScaleDownButton); 455 delete(Data.Display.Axes(:).RecLabel); 456 delete(Data.Display.Axes(:).MaxLabel); 457 delete(Data.Display.Axes(:).MinLabel); 458 delete(Data.Display.Axes(:).DimLabel); 459 delete(Data.Display.Axes(:).PlotLine); 460 delete(Data.Display.Axes(:).Plot); 461 Data.Display.Axes = []; 462end 463 464% draw HScrollBar 465FileDur = LocalGetEDFInfo('FileDur',Data.EDF); 466[MaxVal, MFInd] = max(FileDur); 467Dur = LocalGetEDFInfo('Dur', Data.EDF); 468[MaxDur, MDInd] = max(Dur); 469Len = Data.Display.EDF(MFInd).ShowRecords(1); 470if ~KeepOldPlots 471 Data.Display.HScrollBar = uicontrol(gcf, ... 472 'Style', 'Slider', ... 473 'Units', 'Normalized', ... 474 'Position', [Data.Display.DrawRect(1), 0, ... 475 Data.Display.DrawRect(3), LocalGetFontHeight], ... 476 'SliderStep', [MaxDur/MaxVal 5*MaxDur/MaxVal] * ... 477 Data.Display.EDF(MDInd).ShowRecords(2), ... 478 'Min', 0, ... 479 'Max', 1, ... 480 'Value', Data.Display.EDF(MFInd).ShowRecords(1)/MaxVal*Dur(MFInd), ... 481 'CallBack', 'viewedf HScroll'); 482else 483 set(Data.Display.HScrollBar, ... 484 'Value', Data.Display.EDF(MFInd).ShowRecords(1)/MaxVal*Dur(MFInd)); 485end 486 487%create new buttons, plots and labels 488cnt = 0; 489for j=1:length(Data.EDF) 490 for i=1:length(Data.Display.EDF(j).ShowSignals) 491 cnt = cnt+1; 492 showsig = Data.Display.EDF(j).ShowSignals(i); 493 if ~KeepOldPlots 494 % make new plots, buttons, labels 495 Opt.YPos = Opt.FigY - Opt.YSpace*(cnt-1) - Opt.FigHeight * cnt; 496 Opt.DisplayMin = Data.Display.EDF(j).DisplayMin(showsig); 497 Opt.DisplayMax = Data.Display.EDF(j).DisplayMax(showsig); 498 Opt.UserData = { 'EDF', showsig, j}; 499 Opt.Label = Data.EDF(j).Head.Label(showsig,:); 500 %Opt.YLabel = deblank(Data.EDF(j).Head.PhysDim(showsig,:)); 501 Opt.YLabel = deblank(Data.EDF(j).Head.PhysDim{showsig}); 502 yd = Data.EDF(j).Record{showsig}; 503 if (length(yd) ~= 1) 504 yd = [yd(:); NaN]; 505 end 506 507 Temp = ... 508 LocalPlotNewData(yd, ... 509 Data.Display.EDF(j).UpDownPlot(showsig), ... 510 Data.Display.EDF(j).StairPlot(showsig), Opt); 511 if cnt == 1 512 Data.Display.Axes = Temp; 513 else 514 Data.Display.Axes(cnt) = Temp; 515 end 516 else 517 % set new ydata 518 yd = Data.EDF(j).Record{showsig} * ... 519 (Data.Display.EDF(j).UpDownPlot(showsig)-0.5) * -2; 520 if (length(yd) == 1) 521 yd = yd([1 1]); 522 else 523 yd = yd(1:ceil(length(yd)/Opt.XPixels):length(yd)); 524 yd = [yd(:); NaN]; 525 if Data.Display.EDF(j).StairPlot(showsig) 526 yd = yd(floor(1:0.5:length(yd))); 527 end 528 end 529 set(Data.Display.Axes(cnt).PlotLine, 'YData', yd); 530 end 531 end 532end 533 534% plot plugin-data 535for j = 1:length(Data.Plugin) 536 for i=1:length(Data.Display.Plugin(j).ShowSignals) 537 cnt = cnt+1; 538 showsig = Data.Display.Plugin(j).ShowSignals(i); 539 if ~KeepOldPlots 540 % make new plots, buttons, labels 541 Opt.YPos = Opt.FigY - Opt.YSpace*(cnt-1) - Opt.FigHeight * cnt; 542 Opt.DisplayMin = Data.Display.Plugin(j).DisplayMin(showsig); 543 Opt.DisplayMax = Data.Display.Plugin(j).DisplayMax(showsig); 544 Opt.UserData = { 'PLUGIN', showsig, j}; 545 Opt.Label = Data.Plugin(j).EDF.Head.Label(showsig,:); 546 %Opt.YLabel = deblank(Data.Plugin(j).EDF.Head.PhysDim(showsig,:)); 547 Opt.YLabel = deblank(Data.Plugin(j).EDF.Head.PhysDim{showsig}); 548 yd = Data.Plugin(j).EDF.Record{showsig}; 549 if (length(yd) ~= 1) 550 yd = [yd(:); NaN]; 551 end 552 Data.Display.Axes(cnt) = ... 553 LocalPlotNewData(yd, ... 554 Data.Display.Plugin(j).UpDownPlot(showsig), ... 555 Data.Display.Plugin(j).StairPlot(showsig), Opt); 556 else 557 yd = Data.Plugin(j).EDF.Record{showsig} * ... 558 (Data.Display.Plugin(j).UpDownPlot(showsig)-0.5) * -2; 559 if (length(yd) == 1) 560 yd = yd([1 1]); 561 else 562 yd = yd(1:ceil(length(yd)/Opt.XPixels):length(yd)); 563 yd = [yd(:); NaN]; 564 if Data.Display.Plugin(j).StairPlot(showsig) 565 yd = yd(floor(1:0.5:length(yd))); 566 end 567 end 568 set(Data.Display.Axes(cnt).PlotLine, 'YData', yd); 569 end 570 end 571end 572 573% change size of all strings 574set(Data.Display.Strings.CurrTime, ... 575 'Position', [Opt.TextX, 0, Opt.TextWidth, fhght]); 576pos = get(Data.Display.Strings.TotTime, 'Position'); 577set(Data.Display.Strings.TotTime, ... 578 'Position', [pos(1), 1 - 1.25 * fhght, pos(3), fhght]); 579pos = get(Data.Display.Strings.DispTime, 'Position'); 580set(Data.Display.Strings.DispTime, ... 581 'Position', [pos(1), 1 - 1.25 * fhght, pos(3), fhght]); 582pos = get(Data.Display.Strings.FileName, 'Position'); 583ext = get(Data.Display.Strings.FileName, 'Extent'); 584set(Data.Display.Strings.FileName, ... 585 'Position', [pos(1), 1 - 1.25 * fhght, ext(3) + 0.01, fhght]); 586 587% change size of HScrollBar 588pos = get(Data.Display.HScrollBar, 'Position'); 589set(Data.Display.HScrollBar, ... 590 'Position', [pos(1) pos(2) pos(3) fhght]); 591 592% draw cursor 593if Data.ShowCursor && ~KeepOldPlots, 594 Data.Display.Cursor = LocalDrawCursor(Data.Display); 595end 596 597% display time 598tsec = Data.EDF(1).Head.Dur * Data.Display.EDF(1).ShowRecords(1); 599tmin = floor(tsec/60); 600tsec = rem(tsec,60); 601th = floor(tmin/60); 602tmin = rem(tmin,60); 603set(Data.Display.Strings.CurrTime, 'String', ... 604 sprintf('Time %02d:%02d:%02d', th,tmin,tsec)); 605tsec = Data.EDF(1).Head.Dur * Data.Display.EDF(1).ShowRecords(2); 606tmin = floor(tsec/60); 607tsec = rem(tsec,60); 608th = floor(tmin/60); 609tmin = rem(tmin,60); 610set(Data.Display.Strings.DispTime, 'String', ... 611 sprintf('Displayed : %02d:%02d:%02d', th,tmin,tsec)); 612set(gcf, 'UserData', Data); 613drawnow; 614 615%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 616% LocalPlotNewData 617% plots a single data vector 618function [ploth] = LocalPlotNewData(Data, UpDownPlot, StairPlot, Opt) 619len = length(Data); 620ploth.Plot = subplot('Position', ... 621 [Opt.FigX + Opt.LabelWidth, Opt.YPos, Opt.FigWidth - Opt.LabelWidth, ... 622 Opt.FigHeight - Opt.YSpace]); 623if (len == 1) 624 xd = [1 2]; 625 yd = Data([1 1]); 626else 627 yd = Data(1:ceil(len/Opt.XPixels):len); 628 len = length(yd); 629 if StairPlot 630 xd = ceil(1:0.5:len); 631 yd = yd(floor(1:0.5:len)); 632 else 633 xd = 1:len; 634 end 635end 636 637if UpDownPlot 638 yd = yd * -1; 639 tmp = Opt.DisplayMin; 640 Opt.DisplayMin = -Opt.DisplayMax; 641 Opt.DisplayMax = -tmp; 642end 643 644ploth.PlotLine = plot(xd, yd); 645set(gca, ... 646 'XLim', [1 max([2, len])], ... 647 'YLim', sort([Opt.DisplayMin Opt.DisplayMax])); 648if ~Opt.ShowRange 649 set(gca, ... 650 'XTickLabel', '', ... 651 'YTickLabel', '', ... 652 'XTick', [], ... 653 'YTick', []); 654 ploth.MaxLabel = []; 655 ploth.MinLabel = []; 656 ploth.DimLabel = []; 657else 658 % get TickLabels used by MatLab 659 set(gca, ... 660 'YTick', [Opt.DisplayMin Opt.DisplayMax]); 661 labelstr = get(gca, 'YTickLabel'); 662 labelstr = {deblank(labelstr(1,:)) deblank(labelstr(2,:))}; 663 664 if UpDownPlot 665 for i=1:2 666 if labelstr{i}(1) == '-' 667 labelstr{i} = labelstr{i}(2:length(labelstr{i})); 668 else 669 labelstr{i} = ['-' labelstr{i}]; 670 end 671 end 672 end 673 674 set(gca, 'YTickLabel', ''); 675 % place TickLabels 676 ploth.MinLabel = text(0, 0, ... 677 labelstr{1}, ... 678 'Parent', gca, ... 679 'HorizontalAlignment', 'right', ... 680 'VerticalAlignment', 'baseline', ... 681 'Units', 'normalized'); 682 ploth.MaxLabel = text(0, 1, ... 683 labelstr{2}, ... 684 'Parent', gca, ... 685 'HorizontalAlignment', 'right', ... 686 'VerticalAlignment', 'cap', ... 687 'Units', 'normalized'); 688 % place physical dimension 689 ploth.DimLabel = text(0, 0.5, ... 690 ['[' Opt.YLabel ']'], ... 691 'Parent', gca, ... 692 'HorizontalAlignment', 'right', ... 693 'VerticalAlignment', 'middle', ... 694 'Units', 'normalized'); 695end 696 697ButWidth = Opt.TextWidth / 3; 698ploth.RecButton = uicontrol(gcf, ... 699 'Style', 'PushButton', ... 700 'Units', 'Normalized', ... 701 'String', '?', ... 702 'Position', [Opt.TextX, Opt.YPos, ButWidth, Opt.ButHeight], ... 703 'Callback', 'viewedf RecordProp', ... 704 'UserData', Opt.UserData); 705ploth.ScaleUpButton = uicontrol(gcf, ... 706 'Style', 'PushButton', ... 707 'Units', 'Normalized', ... 708 'String', '+', ... 709 'Position', [Opt.TextX+ButWidth, Opt.YPos, ButWidth, Opt.ButHeight], ... 710 'Callback', 'viewedf ScaleUp', ... 711 'UserData', Opt.UserData); 712ploth.ScaleDownButton = uicontrol(gcf, ... 713 'Style', 'PushButton', ... 714 'Units', 'Normalized', ... 715 'String', '-', ... 716 'Position', [Opt.TextX+2*ButWidth, Opt.YPos, ButWidth, Opt.ButHeight], ... 717 'Callback', 'viewedf ScaleDown', ... 718 'UserData', Opt.UserData); 719ploth.RecLabel = uicontrol(gcf, ... 720 'Style', 'Text', ... 721 'Units', 'Normalized', ... 722 'String', Opt.Label, ... 723 'Position', [Opt.TextX, Opt.YPos + Opt.FigHeight - Opt.YSpace - ... 724 Opt.TxtHeight, Opt.TextWidth, Opt.TxtHeight]); 725 726 727%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 728% LocalAssignMat 729% Save display to Matrix 730function LocalAssignMat() 731Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 732if length(Data.EDF)==0 733 errordlg('No EDF-File is open!', 'Error'); 734 return; 735end 736 737answer = inputdlg({'Target name'}, 'Save to cell-array', 1, {''}); 738if (length(answer) == 0) 739 return; 740end 741cnt = 0; 742for j=1:length(Data.EDF) 743 for i=1:length(Data.Display.EDF(j).ShowSignals) 744 cnt = cnt+1; 745 showsig = Data.Display.EDF(j).ShowSignals(i); 746 res{cnt} = Data.EDF(j).Record{showsig}; 747 end 748end 749for j=1:length(Data.Plugin) 750 for i=1:length(Data.Display.Plugin(j).ShowSignals) 751 cnt = cnt+1; 752 Data.Plugin(j) 753 showsig = Data.Display.Plugin(j).ShowSignals(i); 754 res{cnt} = Data.Plugin(j).EDF.Record{showsig}; 755 end 756end 757assignin('base', answer{1}, res); 758 759%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 760% LocalGetEDFInfo 761% get information of all open EDF files 762function [res] = LocalGetEDFInfo(Which, EDF) 763 764res = []; 765for k=1:length(EDF), 766 switch Which 767 case 'NRec' 768 res = [res,EDF(k).Head.NRec]; 769 case 'Dur' 770 res = [res,EDF(k).Head.SPR / EDF(k).Head.SampleRate]; 771 case 'SPR' 772 res = [res,EDF(k).Head.SPR]; 773 case 'FileDur' 774 res = [res,EDF(k).Head.NRec * EDF(k).Head.SPR / EDF(k).Head.SampleRate]; 775 end 776end; 777 778%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 779% LocalAddPlugin 780% Add plugin function 781function LocalAddPlugin() 782Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 783if length(Data.EDF)==0 784 errordlg('No EDF-File is open!', 'Error'); 785 return; 786end 787 788res=inputdlg({ 'Enter Plugin name','Label (Optional)', ... 789 'Parameters (Optional)'}, 'Select Plugin', 1, { '', '', ''}); 790if isempty(res) 791 return; 792end 793plugname = res{1}; 794pluglabel = res{2}; 795plugopt = res{3}; 796if isempty(pluglabel) 797 pluglabel = plugname; 798end 799if ~exist(plugname, 'file'); 800 errordlg(sprintf('Plugin %s can not be found in standard search path', ... 801 upper(plugname)), 'Plugin Error'); 802 return 803end; 804 805% select EDF file if several files are open 806infile = 1; 807if (length(Data.EDF) > 1) 808 [infile, cancelled] = LocalSelectEDFFile({'EDF-data passed to plugin', ... 809 'Select'}, Data.EDF); 810 if cancelled 811 return 812 end 813end 814 815% set all variables 816ind = length(Data.Plugin) + 1; 817Data.Plugin(ind).Name = plugname; 818Data.Plugin(ind).Label = pluglabel; 819Data.Plugin(ind).UserData = plugopt; 820Data.Plugin(ind).EDFFile = infile; 821LocalWatchOn; 822[Data.Plugin(ind).EDF, Data.Plugin(ind).UserData] = ... 823 feval(Data.Plugin(ind).Name, Data.EDF(infile), ... 824 Data.Plugin(ind).UserData, 'Reset'); 825LocalWatchOff; 826Data.Display.Plugin(ind).ShowSignals = 1:Data.Plugin(ind).EDF.Head.NS; 827Data.Display.Plugin(ind).DisplayMin = Data.Plugin(ind).EDF.Head.PhysMin; 828Data.Display.Plugin(ind).DisplayMax = Data.Plugin(ind).EDF.Head.PhysMax; 829Data.Display.Plugin(ind).StairPlot = ... 830 zeros(1, Data.Plugin(ind).EDF.Head.NS); 831Data.Display.Plugin(ind).UpDownPlot = ... 832 zeros(1, Data.Plugin(ind).EDF.Head.NS); 833MaxDur = max(LocalGetEDFInfo('Dur', Data.EDF)); 834Data.Display.Plugin(ind).ShowRecords = [0 ... 835 round(Data.Plugin(ind).EDF.Head.Dur / MaxDur)]; 836 837% Add menu entry to options menu 838Data.Display.PluginMenu.Sub(ind) = uimenu(Data.Display.PluginMenu.Main, ... 839 'Label', [pluglabel, ' (File ', upper(plugname), ')'], ... 840 'UserData', ind, ... 841 'Callback', 'viewedf PluginMenu'); 842set(findobj('Tag', 'ViewEDFFigure'), 'UserData', Data); 843LocalRepaint(0); 844 845%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 846% LocalRemovePlugin 847% Remove plugin function 848function LocalRemovePlugin(whichplugin) 849Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 850 851if nargin == 0 852 % determine which plugin to remove 853 if length(Data.EDF)==0 854 errordlg('No EDF-File is open!', 'Error'); 855 return; 856 end 857 if length(Data.Plugin) == 0 858 errordlg('No Plugins are loaded!', 'Error'); 859 return; 860 end 861 862 dlgh = dialog(... 863 'Name', 'Remove Plugin', ... 864 'CloseRequestFcn', 'set(gcf,''UserData'',''Cancel'');uiresume;'); 865 dlgpos = get(dlgh, 'Position'); 866 set(dlgh, 'Position', [dlgpos(1),dlgpos(2),200,100]); 867 868 PlugNames = {}; 869 % get Plugin names 870 for i = 1:length(Data.Plugin) 871 PlugNames = {PlugNames{:}, [Data.Plugin(i).Label, ' (File ', ... 872 upper(Data.Plugin(i).Name), ')']}; 873 end 874 875 poph = uicontrol(dlgh, ... 876 'Style', 'Popup', ... 877 'Units', 'Normalized', ... 878 'String', PlugNames, ... 879 'Value', 1, ... 880 'Position', [0.05, 0.5, 0.9, 0.35]); 881 % buttons 882 uicontrol(dlgh, ... 883 'Style', 'PushButton', ... 884 'Units', 'Normalized', ... 885 'String', 'Remove', ... 886 'Position', [0.1, 0.05, 0.3, 0.3], ... 887 'Callback', 'set(gco,''UserData'',''OK'');uiresume;'); 888 uicontrol(dlgh, ... 889 'Style', 'PushButton', ... 890 'Units', 'Normalized', ... 891 'String', 'Cancel', ... 892 'Position', [0.6, 0.05, 0.3, 0.3], ... 893 'Callback', 'set(gco,''UserData'',''Cancel'');uiresume;'); 894 895 drawnow; 896 uiwait(dlgh); 897 whichplugin = get(poph, 'Value'); 898 selbutton = get(gco,'UserData'); 899 delete(dlgh); 900 if strcmp(selbutton,'Cancel') 901 return 902 end 903end 904 905delete(Data.Display.PluginMenu.Sub(whichplugin)); 906for i = whichplugin:length(Data.Plugin)-1 907 Data.Display.PluginMenu.Sub(i) = Data.Display.PluginMenu.Sub(i+1); 908 set(Data.Display.PluginMenu.Sub(i), 'UserData', i); 909 Data.Display.Plugin(i) = Data.Display.Plugin(i+1); 910 Data.Plugin(i) = Data.Plugin(i+1); 911end 912ind = length(Data.Plugin) - 1; 913if ind == 0 914 Data.Plugin = []; 915 Data.Display.Plugin = []; 916 Data.Display.PluginMenu.Sub = []; 917else 918 Data.Plugin = Data.Plugin(1:ind); 919 Data.Display.Plugin = Data.Display.Plugin(1:ind); 920 Data.Display.PluginMenu.Sub = Data.Display.PluginMenu.Sub(1:ind); 921end 922set(findobj('Tag', 'ViewEDFFigure'), 'UserData', Data); 923LocalRepaint; 924 925%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 926% LocalPluginMenu 927% Call plugin for setup 928function LocalPluginMenu() 929ind = get(gcbo, 'UserData'); 930Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 931[Data.Plugin(ind).EDF, Data.Plugin(ind).UserData] = ... 932 feval(Data.Plugin(ind).Name, Data.EDF(Data.Plugin(ind).EDFFile), ... 933 Data.Plugin(ind).UserData, 'Menu'); 934% Uncomment to reset display properties after a call of the plugin-menu 935%Data.Display.Plugin(ind).ShowSignals = 1:Data.Plugin(ind).EDF.Head.NS; 936%Data.Display.Plugin(ind).DisplayMin = Data.Plugin(ind).EDF.Head.PhysMin; 937%Data.Display.Plugin(ind).DisplayMax = Data.Plugin(ind).EDF.Head.PhysMax; 938%Data.Display.Plugin(ind).StairPlot = ... 939% zeros(1, Data.Plugin(ind).EDF.Head.NS); 940%Data.Display.Plugin(ind).UpDownPlot = ... 941% zeros(1, Data.Plugin(ind).EDF.Head.NS); 942set(findobj('Tag', 'ViewEDFFigure'), 'UserData',Data); 943LocalRepaint(0); 944 945%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 946% LocalChangeRecord 947% Change displayed page 948function LocalChangeRecord(increment, changetype) 949Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 950if length(Data.EDF) == 0 951 errordlg('No EDF-File is open!', 'Error'); 952 return; 953end 954Dur = LocalGetEDFInfo('Dur',Data.EDF); 955[MDur, MDInd] = max(Dur); 956FLen = max(LocalGetEDFInfo('FileDur', Data.EDF)); 957[MFLen, MFInd] = max(FLen); 958 959RelInc = round(ones(size(Dur)) * max(Dur) ./ Dur); 960Inc = increment * RelInc; 961 962for i = 1:length(Data.EDF) 963 switch changetype 964 case 0 % incremental 965 Data.Display.EDF(i).ShowRecords(1) = Data.Display.EDF(i).ShowRecords(1) ... 966 + Inc(i) * Data.Display.EDF(MDInd).ShowRecords(2); 967 case 1 % absolute 968 Data.Display.EDF(i).ShowRecords(1) = Inc(i); 969 end 970end 971 972% check whether we are moving to far 973temp = Data.Display.EDF(MDInd).ShowRecords(1); 974if temp < 0 975 for i = 1:length(Data.EDF) 976 Data.Display.EDF(i).ShowRecords(1) = Data.Display.EDF(i).ShowRecords(1) ... 977 - temp * RelInc(i); 978 end 979end 980 981temp = sum(Data.Display.EDF(MFInd).ShowRecords(1:2)) - ... 982 Data.EDF(MFInd).Head.NRec; 983if temp > 0 984 temp = ceil(temp / RelInc(MFInd)); 985 for i = 1:length(Data.EDF) 986 Data.Display.EDF(i).ShowRecords(1) = Data.Display.EDF(i).ShowRecords(1) - ... 987 temp * RelInc(i); 988 end 989end 990 991for i=1:length(Data.EDF) 992 temp = sum(Data.Display.EDF(i).ShowRecords(1:2)) - ... 993 Data.EDF(i).Head.NRec; 994 whichrec(1) = Data.Display.EDF(i).ShowRecords(1); 995 if temp > 0 996 % do not read to much data 997 whichrec(2) = Data.Display.EDF(i).ShowRecords(2) - temp; 998 if (whichrec(2) < 0) 999 whichrec(2) = 0; 1000 end 1001 [temp, Data.EDF(i).Head] = LocalEDFRead(Data.EDF(i).Head, whichrec); 1002 for j = 1:Data.EDF(i).Head.NS 1003 Data.EDF(i).Record{j} = zeros(Data.Display.EDF(i).ShowRecords(2) * ... 1004 Data.EDF(i).Head.SPR(j)); 1005 if ~isempty(temp) 1006 Data.EDF(i).Record{j}(1:length(temp{j})) = temp{j}; 1007 end 1008 end 1009 1010 else 1011 [Data.EDF(i).Record, Data.EDF(i).Head] = ... 1012 LocalEDFRead(Data.EDF(i).Head, Data.Display.EDF(i).ShowRecords); 1013 end 1014end 1015set(findobj('Tag', 'ViewEDFFigure'), 'UserData', Data); 1016LocalRepaint(1); 1017 1018%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1019% LocalHSroll 1020% Goto record 1021function LocalHScroll 1022Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 1023MaxVal = max(LocalGetEDFInfo('FileDur',Data.EDF)); 1024MaxDur = max(LocalGetEDFInfo('Dur', Data.EDF)); 1025pos = get(gcbo, 'Value'); 1026LocalChangeRecord(round(pos*MaxVal/MaxDur), 1); 1027 1028%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1029% LocalGotoRecord 1030% Goto record 1031function LocalGotoRecord(Pos) 1032Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 1033if length(Data.EDF)==0 1034 errordlg('No EDF-File is open!', 'Error'); 1035 return; 1036end 1037 1038[temp, ind] = max(LocalGetEDFInfo('Dur', Data.EDF)); 1039 1040if (nargin == 0) 1041 answer = inputdlg({'Select record'}, 'Change start record', 1, ... 1042 {int2str(Data.Display.EDF(ind).ShowRecords(1))}); 1043 if (length(answer) ~= 0) 1044 answer = str2num(answer{1}); 1045 if ~isempty(answer) 1046 LocalChangeRecord(answer, 1); 1047 end 1048 end 1049else 1050 Pos = round(Pos); 1051 if Pos >= 0 1052 LocalChangeRecord(Pos, 1); 1053 end 1054end 1055 1056 1057%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1058% LocalGotoSecond 1059% Goto second 1060function LocalGotoSecond(Pos) 1061Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 1062if length(Data.EDF)==0 1063 errordlg('No EDF-File is open!', 'Error'); 1064 return; 1065end 1066 1067[temp, ind] = max(LocalGetEDFInfo('Dur', Data.EDF)); 1068 1069if (nargin == 0) 1070 answer = inputdlg({'Select second'}, 'Change start time', 1, ... 1071 {int2str(round(Data.Display.EDF(ind).ShowRecords(1) / ... 1072 Data.EDF(ind).Head.Dur))}); 1073 if (length(answer) ~= 0) 1074 answer = str2num(answer{1}); 1075 if ~isempty(answer) 1076 LocalChangeRecord(answer / Data.EDF(ind).Head.Dur, 1); 1077 end 1078 end 1079else 1080 Pos = round(Pos / Data.EDF(ind).Head.Dur); 1081 if Pos >= 0 1082 LocalChangeRecord(Pos, 1); 1083 end 1084end 1085 1086 1087%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1088% LocalRecordProp 1089% display channel properties 1090function LocalRecordProp() 1091Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 1092if length(Data.EDF)==0 1093 errordlg('No EDF-File is open!', 'Error'); 1094 return; 1095end 1096 1097whichbut = get(gcbo, 'UserData'); 1098Rec = whichbut{2}; 1099Num = whichbut{3}; 1100switch whichbut{1} 1101 case 'EDF' 1102 RecHead = Data.EDF(Num).Head; 1103 RecDisp = Data.Display.EDF(Num); 1104 DataType = 'EDF File'; 1105 TypeString = 'Filename :'; 1106 OptString = [Data.EDF(Num).Head.FILE.Name '.' Data.EDF(Num).Head.FILE.Ext]; 1107 case 'PLUGIN' 1108 RecHead = Data.Plugin(Num).EDF.Head; 1109 RecDisp = Data.Display.Plugin(Num); 1110 DataType = 'Plugin'; 1111 TypeString = 'Name :'; 1112 OptString = Data.Plugin(Num).Label; 1113end 1114dlgh = dialog(... 1115 'Name', 'Channel Information', ... 1116 'CloseRequestFcn', 'set(gcf,''UserData'',''Cancel'');uiresume;'); 1117dlgpos = get(dlgh, 'Position'); 1118set(dlgh, 'Position', [dlgpos(1),dlgpos(2),350,300]); 1119Fnthgt = LocalGetFontHeight; 1120yinc = 0.085; 1121% general information 1122linenum=1; 1123uicontrol(dlgh, ... 1124 'Style', 'Text', ... 1125 'Units', 'Normalized', ... 1126 'HorizontalAlignment', 'left', ... 1127 'FontWeight', 'bold', ... 1128 'String', [ 'Record read from ' DataType], ... 1129 'Position', [0.02, 1-linenum*yinc, 0.96, Fnthgt ]); 1130% filename 1131linenum=linenum+1; 1132uicontrol(dlgh, ... 1133 'Style', 'Text', ... 1134 'Units', 'Normalized', ... 1135 'HorizontalAlignment', 'left', ... 1136 'String', TypeString, ... 1137 'Position', [0.02, 1-linenum*yinc, 0.96, Fnthgt]); 1138uicontrol(dlgh, ... 1139 'Style', 'Text', ... 1140 'Units', 'Normalized', ... 1141 'HorizontalAlignment', 'left', ... 1142 'FontWeight', 'bold', ... 1143 'String', OptString, ... 1144 'Position', [0.35, 1-linenum*yinc, 0.63, Fnthgt]); 1145% label 1146linenum=linenum+1; 1147uicontrol(dlgh, ... 1148 'Style', 'Text', ... 1149 'Units', 'Normalized', ... 1150 'HorizontalAlignment', 'left', ... 1151 'String', 'Label : ', ... 1152 'Position', [0.02, 1-linenum*yinc, 0.96, Fnthgt]); 1153uicontrol(dlgh, ... 1154 'Style', 'Text', ... 1155 'Units', 'Normalized', ... 1156 'HorizontalAlignment', 'left', ... 1157 'FontWeight', 'bold', ... 1158 'String', RecHead.Label(Rec,:), ... 1159 'Position', [0.35, 1-linenum*yinc, 0.63, Fnthgt]); 1160% Transducer 1161linenum=linenum+1; 1162uicontrol(dlgh, ... 1163 'Style', 'Text', ... 1164 'Units', 'Normalized', ... 1165 'HorizontalAlignment', 'left', ... 1166 'String', 'Transducer :', ... 1167 'Position', [0.02, 1-linenum*yinc, 0.96, Fnthgt]); 1168uicontrol(dlgh, ... 1169 'Style', 'Text', ... 1170 'Units', 'Normalized', ... 1171 'HorizontalAlignment', 'left', ... 1172 'FontWeight', 'bold', ... 1173 'String', RecHead.Transducer(Rec, :), ... 1174 'Position', [0.35, 1-linenum*yinc, 0.63, Fnthgt]); 1175% Prefilter 1176linenum=linenum+1; 1177uicontrol(dlgh, ... 1178 'Style', 'Text', ... 1179 'Units', 'Normalized', ... 1180 'HorizontalAlignment', 'left', ... 1181 'String', 'Prefilter :', ... 1182 'Position', [0.02, 1-linenum*yinc, 0.96, Fnthgt]); 1183uicontrol(dlgh, ... 1184 'Style', 'Text', ... 1185 'Units', 'Normalized', ... 1186 'HorizontalAlignment', 'left', ... 1187 'FontWeight', 'bold', ... 1188 'String', RecHead.PreFilt(Rec, :), ... 1189 'Position', [0.35, 1-linenum*yinc, 0.63, Fnthgt]); 1190% samples per records 1191linenum=linenum+1; 1192uicontrol(dlgh, ... 1193 'Style', 'Text', ... 1194 'Units', 'Normalized', ... 1195 'HorizontalAlignment', 'left', ... 1196 'String', 'Samples per record :', ... 1197 'Position', [0.02, 1-linenum*yinc, 0.96, Fnthgt]); 1198uicontrol(dlgh, ... 1199 'Style', 'Text', ... 1200 'Units', 'Normalized', ... 1201 'HorizontalAlignment', 'left', ... 1202 'FontWeight', 'bold', ... 1203 'String', sprintf('%d', RecHead.SPR), ... 1204 'Position', [0.35, 1-linenum*yinc, 0.63, Fnthgt]); 1205% physical min 1206linenum=linenum+1; 1207uicontrol(dlgh, ... 1208 'Style', 'Text', ... 1209 'Units', 'Normalized', ... 1210 'HorizontalAlignment', 'left', ... 1211 'String', 'Physical min :', ... 1212 'Position', [0.02, 1-linenum*yinc, 0.45, Fnthgt]); 1213uicontrol(dlgh, ... 1214 'Style', 'Text', ... 1215 'Units', 'Normalized', ... 1216 'HorizontalAlignment', 'left', ... 1217 'FontWeight', 'bold', ... 1218 'String', sprintf('%f', RecHead.PhysMin(Rec)), ... 1219 'Position', [0.25, 1-linenum*yinc, 0.25, Fnthgt]); 1220% physical max 1221uicontrol(dlgh, ... 1222 'Style', 'Text', ... 1223 'Units', 'Normalized', ... 1224 'HorizontalAlignment', 'left', ... 1225 'String', 'Physical max :', ... 1226 'Position', [0.52, 1-linenum*yinc, 0.45, Fnthgt]); 1227uicontrol(dlgh, ... 1228 'Style', 'Text', ... 1229 'Units', 'Normalized', ... 1230 'HorizontalAlignment', 'left', ... 1231 'FontWeight', 'bold', ... 1232 'String', sprintf('%f', RecHead.PhysMax(Rec)), ... 1233 'Position', [0.77, 1-linenum*yinc, 0.25, Fnthgt]); 1234% digital min 1235linenum=linenum+1; 1236uicontrol(dlgh, ... 1237 'Style', 'Text', ... 1238 'Units', 'Normalized', ... 1239 'HorizontalAlignment', 'left', ... 1240 'String', 'Digital min :', ... 1241 'Position', [0.02, 1-linenum*yinc, 0.45, Fnthgt]); 1242uicontrol(dlgh, ... 1243 'Style', 'Text', ... 1244 'Units', 'Normalized', ... 1245 'HorizontalAlignment', 'left', ... 1246 'FontWeight', 'bold', ... 1247 'String', sprintf('%d', RecHead.DigMin(Rec)), ... 1248 'Position', [0.25, 1-linenum*yinc, 0.25, Fnthgt]); 1249% digital max 1250uicontrol(dlgh, ... 1251 'Style', 'Text', ... 1252 'Units', 'Normalized', ... 1253 'HorizontalAlignment', 'left', ... 1254 'String', 'Digital max :', ... 1255 'Position', [0.52, 1-linenum*yinc, 0.45, Fnthgt]); 1256uicontrol(dlgh, ... 1257 'Style', 'Text', ... 1258 'Units', 'Normalized', ... 1259 'HorizontalAlignment', 'left', ... 1260 'FontWeight', 'bold', ... 1261 'String', sprintf('%d', RecHead.DigMax(Rec)), ... 1262 'Position', [0.77, 1-linenum*yinc, 0.25, Fnthgt]); 1263% display min 1264linenum=linenum+1; 1265uicontrol(dlgh, ... 1266 'Style', 'Text', ... 1267 'Units', 'Normalized', ... 1268 'HorizontalAlignment', 'left', ... 1269 'String', 'Display min :', ... 1270 'Position', [0.02, 1-linenum*yinc, 0.2, Fnthgt]); 1271dminh = uicontrol(dlgh, ... 1272 'Style', 'Edit', ... 1273 'Units', 'Normalized', ... 1274 'HorizontalAlignment', 'left', ... 1275 'BackGroundColor', [1 1 1], ... 1276 'String', sprintf('%f', RecDisp.DisplayMin(Rec)), ... 1277 'Position', [0.25, 1-linenum*yinc, 0.20, Fnthgt+0.02]); 1278LocalResizeUI(dminh, [NaN 1.1 0 0]); 1279% display max 1280uicontrol(dlgh, ... 1281 'Style', 'Text', ... 1282 'Units', 'Normalized', ... 1283 'HorizontalAlignment', 'left', ... 1284 'String', 'Display max :', ... 1285 'Position', [0.52, 1-linenum*yinc, 0.2, Fnthgt]); 1286dmaxh = uicontrol(dlgh, ... 1287 'Style', 'Edit', ... 1288 'Units', 'Normalized', ... 1289 'HorizontalAlignment', 'left', ... 1290 'BackGroundColor', [1 1 1], ... 1291 'String', sprintf('%f', RecDisp.DisplayMax(Rec)), ... 1292 'Position', [0.77, 1-linenum*yinc, 0.20, Fnthgt+0.02]); 1293LocalResizeUI(dmaxh, [NaN 1.1 0 0]); 1294% Plot-type 1295linenum=linenum+1; 1296ploth = uicontrol(dlgh, ... 1297 'Style', 'CheckBox', ... 1298 'Units', 'Normalized', ... 1299 'String', ' Stairstep-Plot', ... 1300 'Value', RecDisp.StairPlot(Rec), ... 1301 'Position', [0.02, 1-linenum*yinc, 0.7, Fnthgt]); 1302LocalResizeUI(ploth, [1 1 0.05 0]); 1303% Invert plot 1304updownh = uicontrol(dlgh, ... 1305 'Style', 'CheckBox', ... 1306 'Units', 'Normalized', ... 1307 'String', ' Plot upside down', ... 1308 'Value', RecDisp.UpDownPlot(Rec), ... 1309 'Position', [0.52, 1-linenum*yinc, 0.7, Fnthgt]); 1310LocalResizeUI(updownh, [1 1 0.05 0]); 1311% buttons 1312linenum=linenum+1; 1313uicontrol(dlgh, ... 1314 'Style', 'PushButton', ... 1315 'Units', 'Normalized', ... 1316 'String', 'OK', ... 1317 'Position', [0.05, 0.02, 0.3, 0.08], ... 1318 'Callback', 'set(gco,''UserData'',''OK'');uiresume;'); 1319uicontrol(dlgh, ... 1320 'Style', 'PushButton', ... 1321 'Units', 'Normalized', ... 1322 'String', 'Apply to all', ... 1323 'Position', [0.4, 0.02, 0.2, 0.08], ... 1324 'Callback', 'set(gco,''UserData'',''ApplyAll'');uiresume;'); 1325uicontrol(dlgh, ... 1326 'Style', 'PushButton', ... 1327 'Units', 'Normalized', ... 1328 'String', 'Cancel', ... 1329 'Position', [0.65, 0.02, 0.3, 0.08], ... 1330 'Callback', 'set(gco,''UserData'',''Cancel'');uiresume;'); 1331 1332drawnow; 1333uiwait(dlgh); 1334changed = 0; 1335if ~strcmp(get(gco,'UserData'),'Cancel') 1336 dmin = str2num(get(dminh, 'String')); 1337 dmax = str2num(get(dmaxh, 'String')); 1338 stplot = get(ploth, 'Value'); 1339 udplot = get(updownh, 'Value'); 1340 if (length(dmin) == 1) && (length(dmax) == 1) && (dmin < dmax), 1341 changed = 1; 1342 if strcmp(get(gco,'UserData'),'OK') 1343 switch(whichbut{1}) 1344 case 'EDF' 1345 Data.Display.EDF(Num).DisplayMin(Rec) = dmin; 1346 Data.Display.EDF(Num).DisplayMax(Rec) = dmax; 1347 Data.Display.EDF(Num).StairPlot(Rec) = stplot; 1348 Data.Display.EDF(Num).UpDownPlot(Rec) = udplot; 1349 case 'PLUGIN' 1350 Data.Display.Plugin(Num).DisplayMin(Rec) = dmin; 1351 Data.Display.Plugin(Num).DisplayMax(Rec) = dmax; 1352 Data.Display.Plugin(Num).StairPlot(Rec) = stplot; 1353 Data.Display.Plugin(Num).UpDownPlot(Rec) = udplot; 1354 end 1355 else 1356 % set all files 1357 for fnum = 1:length(Data.Display.EDF) 1358 for rec = 1:length(Data.Display.EDF(fnum).DisplayMin) 1359 Data.Display.EDF(fnum).DisplayMin(rec) = dmin; 1360 Data.Display.EDF(fnum).DisplayMax(rec) = dmax; 1361 Data.Display.EDF(fnum).StairPlot(rec) = stplot; 1362 Data.Display.EDF(fnum).UpDownPlot(rec) = udplot; 1363 end 1364 end 1365 if isfield(Data.Display, 'Plugin') 1366 for fnum = 1:length(Data.Display.Plugin) 1367 for rec = 1:length(Data.Display.Plugin(fnum).DisplayMin) 1368 Data.Display.Plugin(fnum).DisplayMin(rec) = dmin; 1369 Data.Display.Plugin(fnum).DisplayMax(rec) = dmax; 1370 Data.Display.Plugin(fnum).StairPlot(rec) = stplot; 1371 Data.Display.Plugin(fnum).UpDownPlot(rec) = udplot; 1372 end 1373 end 1374 end 1375 end 1376 end 1377end 1378delete(dlgh); 1379if changed 1380 set(findobj('Tag', 'ViewEDFFigure'), 'UserData', Data); 1381 LocalRepaint; 1382end 1383 1384%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1385% LocalRescale 1386% change range of a plot 1387function LocalRescale(Mode) 1388Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 1389whichbut = get(gcbo, 'UserData'); 1390Rec = whichbut{2}; 1391Num = whichbut{3}; 1392 1393switch(whichbut{1}) 1394 case 'EDF' 1395 DisData = Data.Display.EDF(Num); 1396 [DisData.DisplayMin(Rec), DisData.DisplayMax(Rec)] = ... 1397 LocalCalcNewRange(DisData.DisplayMin(Rec), DisData.DisplayMax(Rec), ... 1398 Mode); 1399 Data.Display.EDF(Num) = DisData; 1400 case 'PLUGIN' 1401 DisData = Data.Display.Plugin(Num); 1402 [DisData.DisplayMin(Rec), DisData.DisplayMax(Rec)] = ... 1403 LocalCalcNewRange(DisData.DisplayMin(Rec), DisData.DisplayMax(Rec), ... 1404 Mode); 1405 Data.Display.Plugin(Num) = DisData; 1406end 1407set(findobj('Tag', 'ViewEDFFigure'), 'UserData', Data); 1408LocalRepaint; 1409 1410%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1411% LocalRescaleAll 1412% change range of all plots 1413function LocalRescaleAll(Mode) 1414Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 1415if length(Data.EDF)==0 1416 return; 1417end 1418% EDF files 1419for i=1:length(Data.EDF) 1420 DisData = Data.Display.EDF(i); 1421 [DisData.DisplayMin, DisData.DisplayMax] = ... 1422 LocalCalcNewRange(DisData.DisplayMin, DisData.DisplayMax, Mode); 1423 Data.Display.EDF(i) = DisData; 1424end 1425% plugins 1426for i=1:length(Data.Plugin) 1427 DisData = Data.Display.Plugin(i); 1428 [DisData.DisplayMin, DisData.DisplayMax] = ... 1429 LocalCalcNewRange(DisData.DisplayMin, DisData.DisplayMax, Mode); 1430 Data.Display.Plugin(i) = DisData; 1431end 1432set(findobj('Tag', 'ViewEDFFigure'), 'UserData', Data); 1433LocalRepaint; 1434 1435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1436% LocalCalcNewRange 1437% calculate new range for plots 1438function [ResMin, ResMax] = LocalCalcNewRange(PMin, PMax, Mode) 1439dmean = (PMin+PMax) / 2; 1440switch Mode 1441 case 'up' 1442 ResMin = (PMin - dmean)*0.5 + dmean; 1443 ResMax = (PMax - dmean)*0.5 + dmean; 1444 case 'down' 1445 ResMin = (PMin - dmean)*2 + dmean; 1446 ResMax = (PMax - dmean)*2 + dmean; 1447 otherwise 1448 ResMin = PMin; 1449 ResMax = PMax; 1450end 1451 1452 1453%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1454% LocalToggleUpdatePlugin 1455% Toggle flag for updating plugin-results 1456function LocalToggleUpdatePlugin() 1457Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 1458Data.UpdatePlugin = ~Data.UpdatePlugin; 1459if Data.UpdatePlugin 1460 set(gcbo, 'Checked', 'on'); 1461else 1462 set(gcbo, 'Checked', 'off'); 1463end 1464set(findobj('Tag', 'ViewEDFFigure'), 'UserData', Data); 1465 1466%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1467% LocalToggleShowRange 1468% Toggle flag for showing plot ranges 1469function LocalToggleShowRange() 1470Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 1471Data.ShowRange = ~Data.ShowRange; 1472if Data.ShowRange 1473 set(gcbo, 'Checked', 'on'); 1474else 1475 set(gcbo, 'Checked', 'off'); 1476end 1477set(findobj('Tag', 'ViewEDFFigure'), 'UserData', Data); 1478LocalRepaint; 1479 1480%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1481% LocalToggleShowCursor 1482% Toggle flag for showing cursor 1483function LocalToggleShowCursor() 1484figure(findobj('Tag', 'ViewEDFFigure')); 1485Data = get(gcf, 'UserData'); 1486Data.ShowCursor = ~Data.ShowCursor; 1487if Data.ShowCursor 1488 set(gcbo, 'Checked', 'on'); 1489 set(gcf, 'WindowButtonDownFcn', 'viewedf MoveCursor Down'); 1490 Data.Display.Cursor = LocalDrawCursor(Data.Display); 1491else 1492 delete(Data.Display.Cursor.Line(:)); 1493 delete(Data.Display.Cursor.Menu.Text); 1494 delete(Data.Display.Cursor.Menu.Menu); 1495 Data.Display.Cursor = []; 1496 set(gcbo, 'Checked', 'off'); 1497 set(gcf, 'WindowButtonMotionFcn', '', ... 1498 'WindowButtonDownFcn', '', ... 1499 'WindowButtonUpFcn', ''); 1500end 1501set(gcf, 'UserData', Data); 1502 1503%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1504% LocalDrawCursor 1505% Show cursor 1506function Cursor = LocalDrawCursor(DisplayData, NewPos, TimeStr) 1507if nargin ~= 3 1508 % find good placement for lines 1509 Cursor.Pos = 0.5; 1510 Cursor.Menu.Menu = uicontextmenu; 1511 Cursor.Menu.Text = uimenu(Cursor.Menu.Menu, ... 1512 'Label', '', ... 1513 'Callback', ''); 1514 % generate lines 1515 for i=1:length(DisplayData.Axes) 1516 Cursor.AxesLim(i, :) = get(DisplayData.Axes(i).Plot, 'XLim'); 1517 XPos = Cursor.AxesLim(i,1) + (Cursor.AxesLim(i,2) - Cursor.AxesLim(i,1)) ... 1518 * Cursor.Pos; 1519 Cursor.Line(i) = line('Parent', DisplayData.Axes(i).Plot, ... 1520 'XData', [XPos XPos], ... 1521 'YData', get(DisplayData.Axes(i).Plot, 'YLim'), ... 1522 'EraseMode', 'xor', ... 1523 'UIContextMenu', Cursor.Menu.Menu, ... 1524 'Color', [1 0.2 0.2]); 1525 Cursor.AxesPos(i, :) = get(DisplayData.Axes(i).Plot, 'Position'); 1526 end 1527else 1528 Cursor = DisplayData.Cursor; 1529 Cursor.Pos = NewPos; 1530 for i=1:length(DisplayData.Axes) 1531 XPos = Cursor.AxesLim(i,1) + (Cursor.AxesLim(i,2) - Cursor.AxesLim(i,1)) ... 1532 * Cursor.Pos; 1533 set(Cursor.Line(i), 'XData', [XPos XPos]); 1534 end 1535 set(Cursor.Menu.Text, 'Label', TimeStr); 1536end 1537 1538%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1539% LocalMoveCursor 1540% Move cursor 1541function LocalMoveCursor(Option) 1542Data = get(gcf, 'UserData'); 1543CurrPt = get(gcf, 'CurrentPoint'); 1544% check if click was in axis 1545AxPos = Data.Display.Cursor.AxesPos; 1546temp = CurrPt(1) > AxPos(:,1) & CurrPt(1) < (AxPos(:,1) + AxPos(:,3)) & ... 1547 CurrPt(2) > AxPos(:,2) & CurrPt(2) < (AxPos(:,2) + AxPos(:,4)); 1548if ~any(temp) 1549 return; 1550end 1551 1552% find axis under pointer and calculate position 1553ax = find(temp); 1554Pos = get(Data.Display.Axes(ax).Plot, 'CurrentPoint'); 1555Pos = Pos(2,1); 1556Pos = (Pos - Data.Display.Cursor.AxesLim(ax,1)) / (Data.Display.Cursor.AxesLim(ax,2) ... 1557 - Data.Display.Cursor.AxesLim(ax,1)); 1558 1559tsec = Data.EDF(1).Head.Dur * Data.Display.EDF(1).ShowRecords(1) + ... 1560 Data.EDF(1).Head.Dur * Data.Display.EDF(1).ShowRecords(2) * Pos; 1561tmin = floor(tsec/60); 1562tsec = rem(tsec,60); 1563th = floor(tmin/60); 1564tmin = rem(tmin, 60); 1565TimeStr = sprintf('%02d:%02d:%02.1f', th,tmin,tsec); 1566 1567switch Option 1568 case 'Down' 1569 Data.Display.Cursor = LocalDrawCursor(Data.Display, Pos, TimeStr); 1570 set(gcf, 'WindowButtonMotionFcn', 'viewedf MoveCursor Move', ... 1571 'WindowButtonUpFcn', 'viewedf MoveCursor Up'); 1572 case 'Move' 1573 Data.Display.Cursor = LocalDrawCursor(Data.Display, Pos, TimeStr); 1574 case 'Up' 1575 set(gcf, 'WindowButtonMotionFcn', ''); 1576end 1577set(gcf, 'UserData', Data); 1578 1579%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1580% LocalResizeUI 1581% resize UI control according to label size 1582function uihandle = LocalResizeUI(uihandle, options) 1583if nargin < 2 1584 options = [1 1 0 0]; 1585end 1586ext = get(uihandle, 'Extent'); 1587pos = get(uihandle, 'Position'); 1588if ~isnan(options(1)) 1589 pos(3) = ext(3)*options(1) + options(3); 1590end 1591if ~isnan(options(2)) 1592 pos(4) = ext(4)*options(2) + options(4); 1593end 1594set(uihandle, 'Position', pos); 1595 1596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1597% LocalNumRecords 1598% select the number of records to be shown simultaniously 1599function LocalNumRecords() 1600Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 1601if length(Data.EDF) == 0 1602 errordlg('No EDF-File is open!', 'Error'); 1603 return; 1604end 1605 1606Dur = LocalGetEDFInfo('Dur', Data.EDF); 1607[MaxDur, MDInd] = max(Dur); 1608 1609answer = inputdlg({'Select number of records'}, ... 1610 'Number of records on screen', 1, ... 1611 {int2str(Data.Display.EDF(MDInd).ShowRecords(2))}); 1612if (length(answer) ~= 0) 1613 answer = str2num(answer{1}); 1614 if ~isempty(answer) 1615 for i=1:length(Data.EDF) 1616 Data.Display.EDF(i).ShowRecords(2) = answer * MaxDur / Dur(i); 1617 [Data.EDF(i).Record, Data.EDF(i).Head] = ... 1618 LocalEDFRead(Data.EDF(i).Head, Data.Display.EDF(i).ShowRecords); 1619 end 1620 set(findobj('Tag', 'ViewEDFFigure'), 'UserData', Data); 1621 LocalRepaint(0); 1622 end 1623end 1624 1625%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1626% LocalFileInfo 1627% display information about current file 1628function LocalFileInfo(Update) 1629if nargin == 0 1630 Data=get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 1631 if length(Data.EDF)==0 1632 errordlg('No EDF-File is open!', 'Error'); 1633 return; 1634 end 1635 dlgh = dialog(... 1636 'Name', 'EDF-File information', ... 1637 'CloseRequestFcn', 'set(gcf,''UserData'',''Cancel'');uiresume;'); 1638 dlgpos = get(dlgh, 'Position'); 1639 set(dlgh, 'Position', [dlgpos(1),dlgpos(2),450,250]); 1640 fnthght = LocalGetFontHeight; 1641 1642 Local.EDFNames = {}; 1643 % get filenames 1644 for i = 1:length(Data.EDF) 1645 Local.EDFNames = {Local.EDFNames{:}, Data.EDF(i).Head.FileName}; 1646 Local.EDFInfo{i,1} = Data.EDF(i).Head.VERSION; 1647 Local.EDFInfo{i,2} = Data.EDF(i).Head.PID; 1648 Local.EDFInfo{i,3} = Data.EDF(i).Head.RID; 1649 Local.EDFInfo{i,4} = sprintf('%02d/%02d/%02d', Data.EDF(i).Head.T0([3 2 1])); 1650 Local.EDFInfo{i,5} = sprintf('%02d:%02d:%02d', Data.EDF(i).Head.T0([4 5 6])); 1651 Local.EDFInfo{i,6} = sprintf('%d', Data.EDF(i).Head.NS); 1652 Local.EDFInfo{i,7} = sprintf('%d', Data.EDF(i).Head.NRec); 1653 end 1654 1655 Local.poph = uicontrol(dlgh, ... 1656 'Style', 'Popup', ... 1657 'Units', 'Normalized', ... 1658 'String', Local.EDFNames, ... 1659 'Value', 1, ... 1660 'Position', [0.05, 0.9, 0.9, 0.1], ... 1661 'Callback', 'viewedf FileInfo Update'); 1662 LocalResizeUI(Local.poph, [NaN 1.1 0 0]); 1663 %HeaderVersion 1664 num = 1; 1665 yinc = (1 - 4*fnthght) / 8; 1666 ystart = 0.9; 1667 uicontrol(dlgh, ... 1668 'Style', 'Text', ... 1669 'HorizontalAlignment', 'left', ... 1670 'Units', 'Normalized', ... 1671 'String', 'HeaderVersion : ', ... 1672 'Position', [0.05, ystart - num*yinc, 0.3, fnthght]); 1673 Local.txth(num) = uicontrol(dlgh, ... 1674 'Style', 'Text', ... 1675 'HorizontalAlignment', 'left', ... 1676 'Units', 'Normalized', ... 1677 'FontWeight', 'bold', ... 1678 'String', '', ... 1679 'Position', [0.45, ystart - num*yinc, 0.5, fnthght]); 1680 %Patient ID 1681 num = num + 1; 1682 uicontrol(dlgh, ... 1683 'Style', 'Text', ... 1684 'HorizontalAlignment', 'left', ... 1685 'Units', 'Normalized', ... 1686 'String', 'Patient ID : ', ... 1687 'Position', [0.05, ystart - num*yinc, 0.3, fnthght]); 1688 Local.txth(num) = uicontrol(dlgh, ... 1689 'Style', 'Text', ... 1690 'HorizontalAlignment', 'left', ... 1691 'Units', 'Normalized', ... 1692 'FontWeight', 'bold', ... 1693 'String', '', ... 1694 'Position', [0.45, ystart - num*yinc, 0.5, fnthght]); 1695 %Recording ID 1696 num = num + 1; 1697 uicontrol(dlgh, ... 1698 'Style', 'Text', ... 1699 'HorizontalAlignment', 'left', ... 1700 'Units', 'Normalized', ... 1701 'String', 'Recording ID : ', ... 1702 'Position', [0.05, ystart - num*yinc, 0.3, fnthght]); 1703 Local.txth(num) = uicontrol(dlgh, ... 1704 'Style', 'Text', ... 1705 'HorizontalAlignment', 'left', ... 1706 'Units', 'Normalized', ... 1707 'FontWeight', 'bold', ... 1708 'String', '', ... 1709 'Position', [0.45, ystart - num*yinc, 0.5, fnthght]); 1710 % startdate 1711 num = num + 1; 1712 uicontrol(dlgh, ... 1713 'Style', 'Text', ... 1714 'HorizontalAlignment', 'left', ... 1715 'Units', 'Normalized', ... 1716 'String', 'Start date : ', ... 1717 'Position', [0.05, ystart - num*yinc, 0.3, fnthght]); 1718 Local.txth(num) = uicontrol(dlgh, ... 1719 'Style', 'Text', ... 1720 'HorizontalAlignment', 'left', ... 1721 'Units', 'Normalized', ... 1722 'FontWeight', 'bold', ... 1723 'String', '', ... 1724 'Position', [0.45, ystart - num*yinc, 0.5, fnthght]); 1725 % start time 1726 num = num + 1; 1727 uicontrol(dlgh, ... 1728 'Style', 'Text', ... 1729 'HorizontalAlignment', 'left', ... 1730 'Units', 'Normalized', ... 1731 'String', 'Start time : ', ... 1732 'Position', [0.05, ystart - num*yinc, 0.3, fnthght]); 1733 Local.txth(num) = uicontrol(dlgh, ... 1734 'Style', 'Text', ... 1735 'HorizontalAlignment', 'left', ... 1736 'Units', 'Normalized', ... 1737 'FontWeight', 'bold', ... 1738 'String', '', ... 1739 'Position', [0.45, ystart - num*yinc, 0.5, fnthght]); 1740 % Num channels 1741 num = num + 1; 1742 uicontrol(dlgh, ... 1743 'Style', 'Text', ... 1744 'HorizontalAlignment', 'left', ... 1745 'Units', 'Normalized', ... 1746 'String', 'Number of channels : ', ... 1747 'Position', [0.05, ystart - num*yinc, 0.3, fnthght]); 1748 Local.txth(num) = uicontrol(dlgh, ... 1749 'Style', 'Text', ... 1750 'HorizontalAlignment', 'left', ... 1751 'Units', 'Normalized', ... 1752 'FontWeight', 'bold', ... 1753 'String', '', ... 1754 'Position', [0.45, ystart - num*yinc, 0.5, fnthght]); 1755 % num records 1756 num = num + 1; 1757 uicontrol(dlgh, ... 1758 'Style', 'Text', ... 1759 'HorizontalAlignment', 'left', ... 1760 'Units', 'Normalized', ... 1761 'String', 'Number of records : ', ... 1762 'Position', [0.05, ystart - num*yinc, 0.3, fnthght]); 1763 Local.txth(num) = uicontrol(dlgh, ... 1764 'Style', 'Text', ... 1765 'HorizontalAlignment', 'left', ... 1766 'Units', 'Normalized', ... 1767 'FontWeight', 'bold', ... 1768 'String', '', ... 1769 'Position', [0.45, ystart - num*yinc, 0.5, fnthght]); 1770 % buttons 1771 uicontrol(dlgh, ... 1772 'Style', 'PushButton', ... 1773 'Units', 'Normalized', ... 1774 'String', 'OK', ... 1775 'Position', [0.3, 0.02, 0.4, 0.1], ... 1776 'Callback', 'uiresume;'); 1777 Data=[]; 1778 set(dlgh, 'UserData', Local); 1779 LocalFileInfo('Update'); 1780 1781 drawnow; 1782 uiwait(dlgh); 1783 delete(dlgh); 1784else 1785 Data=get(gcf,'UserData'); 1786 which = get(Data.poph, 'Value'); 1787 for i = 1:7 1788 set(Data.txth(i), 'String', Data.EDFInfo{which,i}); 1789 end 1790end 1791 1792%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1793% LocalSelectChannels 1794% select channels to be displayed on the screen 1795function LocalSelectChannels(Parameter) 1796if nargin == 0 1797 Data=get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 1798 if length(Data.EDF)==0 1799 errordlg('No EDF-File is open!', 'Error'); 1800 return; 1801 end 1802 dlgh = dialog(... 1803 'Name', 'EDF-File information', ... 1804 'CloseRequestFcn', 'uiresume;'); 1805 1806 Local.Names = {}; 1807 Local.Selected = {}; 1808 Local.Label = {}; 1809 % get filenames 1810 for i = 1:length(Data.EDF) 1811 Local.Names = {Local.Names{:}, ['EDF: ', Data.EDF(i).Head.FileName]}; 1812 temp = zeros(Data.EDF(i).Head.NS,1); 1813 temp(Data.Display.EDF(i).ShowSignals) = 1; 1814 Local.Selected = {Local.Selected{:}, temp}; 1815 Local.Label = {Local.Label{:}, Data.EDF(i).Head.Label}; 1816 end 1817 %get plugin names 1818 for i = 1:length(Data.Plugin) 1819 Local.Names = {Local.Names{:}, ['Plugin: ', Data.Plugin(i).Label, ... 1820 ' (File ', upper(Data.Plugin(i).Name), ')']}; 1821 temp = zeros(Data.Plugin(i).EDF.Head.NS,1); 1822 temp(Data.Display.Plugin(i).ShowSignals) = 1; 1823 Local.Selected = {Local.Selected{:}, temp}; 1824 Local.Label = {Local.Label{:}, Data.Plugin(i).EDF.Head.Label}; 1825 end 1826 1827 uicontrol(dlgh, ... 1828 'Style', 'Frame', ... 1829 'Units', 'Normalized', ... 1830 'Position', [0.02, 0.12, 0.96, 0.76]); 1831 Local.Poph = uicontrol(dlgh, ... 1832 'Style', 'Popup', ... 1833 'Units', 'Normalized', ... 1834 'String', Local.Names, ... 1835 'Value', 1, ... 1836 'Position', [0.05, 0.9, 0.9, 0.1], ... 1837 'Callback', 'viewedf Channels Update'); 1838 LocalResizeUI(Local.Poph, [NaN 1.1 0 0]); 1839 % buttons 1840 uicontrol(dlgh, ... 1841 'Style', 'PushButton', ... 1842 'Units', 'Normalized', ... 1843 'String', 'Select', ... 1844 'Position', [0.1, 0.14, 0.3, 0.08], ... 1845 'Callback', 'viewedf Channels Select'); 1846 uicontrol(dlgh, ... 1847 'Style', 'PushButton', ... 1848 'Units', 'Normalized', ... 1849 'String', 'Unselect', ... 1850 'Position', [0.6, 0.14, 0.3, 0.08], ... 1851 'Callback', 'viewedf Channels Unselect'); 1852 uicontrol(dlgh, ... 1853 'Style', 'PushButton', ... 1854 'Units', 'Normalized', ... 1855 'String', 'OK', ... 1856 'Position', [0.1, 0.02, 0.3, 0.08], ... 1857 'Callback', 'set(gco,''UserData'',''OK'');uiresume;'); 1858 uicontrol(dlgh, ... 1859 'Style', 'PushButton', ... 1860 'Units', 'Normalized', ... 1861 'String', 'Cancel', ... 1862 'Position', [0.6, 0.02, 0.3, 0.08], ... 1863 'Callback', 'set(gco,''UserData'',''Cancel'');uiresume;'); 1864 Local.Checkh = []; 1865 set(dlgh, 'UserData', Local); 1866 LocalSelectChannels('Update'); % draw information 1867 1868 drawnow; 1869 uiwait(dlgh); 1870 changed = 0; 1871 Local = get(dlgh, 'UserData'); 1872 temp = get(Local.Checkh, 'Value'); 1873 Local.Selected{Local.OldWhich} = cat(1,temp{:}); 1874 if strcmp(get(gco,'UserData'),'OK') 1875 changed = 1; 1876 for i = 1:length(Data.EDF) 1877 Data.Display.EDF(i).ShowSignals = find(Local.Selected{i}); 1878 end 1879 for i = 1:length(Data.Plugin) 1880 Data.Display.Plugin(i).ShowSignals = find(Local.Selected{i+length(Data.EDF)}); 1881 end 1882 end 1883 delete(dlgh); 1884 if changed 1885 set(findobj('Tag', 'ViewEDFFigure'), 'UserData', Data); 1886 LocalRepaint(0); 1887 end 1888else 1889 Data=get(gcf,'UserData'); 1890 which = get(Data.Poph, 'Value'); 1891 switch (Parameter) 1892 case 'Update' 1893 if ~isempty(Data.Checkh) 1894 temp = get(Data.Checkh, 'Value'); 1895 if iscell(temp) 1896 Data.Selected{Data.OldWhich} = cat(1,temp{:}); 1897 else 1898 Data.Selected{Data.OldWhich} = temp; 1899 end 1900 delete(Data.Checkh); 1901 Data.Checkh = []; 1902 end 1903 Data.OldWhich = which; 1904 1905 cbx = 0.1; 1906 cby = 0.82; 1907 cbxspace = 0.4; 1908 cbyspace = 0.6 / ceil(length(Data.Selected{which}) / 2) + 0.005; 1909 cbwidth = 0.35; 1910 cbheight = LocalGetFontHeight; 1911 for i = 1:length(Data.Selected{which}) 1912 Data.Checkh(i) = uicontrol(gcf, ... 1913 'Style', 'CheckBox', ... 1914 'Units', 'Normalized', ... 1915 'String', Data.Label{which}(i, :), ... 1916 'Value', Data.Selected{which}(i), ... 1917 'Position', [cbx + rem(i-1,2)*cbxspace, cby - floor((i-1)/2)*cbyspace, ... 1918 cbwidth, cbheight]); 1919 end 1920 case 'Select' 1921 Data.Selected{which}(:) = 1; 1922 set(Data.Checkh(:), 'Value', 1); 1923 case 'Unselect' 1924 Data.Selected{which}(:) = 0; 1925 set(Data.Checkh(:), 'Value', 0); 1926 end 1927 set(gcf, 'UserData', Data); 1928end 1929 1930%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1931% LocalKeyPress 1932% handle keystrokes 1933function LocalKeyPress() 1934switch upper(get(gcf, 'CurrentCharacter')) 1935 case '+' 1936 feval('viewedf', 'Next'); 1937 case '-' 1938 feval('viewedf', 'Prev'); 1939 case 'U' 1940 LocalRescaleAll('up'); 1941 case 'D' 1942 LocalRescaleAll('down'); 1943end 1944 1945%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1946% LocalAbout 1947% display program info 1948function LocalAbout() 1949helpdlg(sprintf([ 'EDF (European-Data-Format) file-viewer.\n', ... 1950 'Version 3.04Alpha\n\n' ... 1951 '(c) 1998-2001 Herbert Ramoser\n', ... 1952 ' herbert.ramoser@arcs.ac.at\n\n' ... 1953 'Comments or suggestions may be sent to the author.\n\n', ... 1954 'This Software is subject to the GNU public license.']), ... 1955 'About VIEWEDF'); 1956 1957%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1958% LocalHelp 1959% display help page 1960function LocalHelp(Par) 1961name = which('viewedf'); 1962name = [ 'file://', name(1:max(find(name == 'm'))-1), 'html']; 1963web(name); 1964 1965%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1966% LocalPrint 1967% display print dialog 1968function LocalPrint() 1969printdlg('-crossplatform', findobj('Tag', 'ViewEDFFigure')); 1970 1971%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1972% LocalWatchOn 1973% display watch pointer 1974function LocalWatchOn() 1975set(findobj('Tag', 'ViewEDFFigure'), 'Pointer', 'watch'); 1976 1977%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1978% LocalWatchOff 1979% display arrow-pointer 1980function LocalWatchOff() 1981set(findobj('Tag', 'ViewEDFFigure'), 'Pointer', 'arrow'); 1982 1983%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1984% LocalGetFontHeight 1985% get Fontheight 1986function hght=LocalGetFontHeight() 1987tempH = uicontrol(... 1988 'Style', 'Text', ... 1989 'String', 'Gg', ... 1990 'Units', 'Normalized', ... 1991 'FontUnits', 'Normalized', ... 1992 'Position', [0, 0, 1, 1], ... 1993 'Visible', 'off'); 1994t = get(tempH); 1995hght = getfield(t, 'FontSize') * 1.25; % 1.25 makes things look better 1996delete(tempH); 1997 1998 1999%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2000% LocalGetFontWidth 2001% get Fontwidth 2002function width=LocalGetFontWidth() 2003tempH = uicontrol(... 2004 'Style', 'Text', ... 2005 'String', 'X', ... 2006 'Units', 'Normalized', ... 2007 'FontUnits', 'Normalized', ... 2008 'Position', [0, 0, 1, 1], ... 2009 'Visible', 'off'); 2010width = get(tempH, 'Extent'); 2011width = width(3); 2012delete(tempH); 2013 2014 2015%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2016% LocalEDFOpen 2017% open a EDF (or GDF) file 2018function LocalEDFOpen(Filename) 2019% show EDF header errors 2020ShowHeadErr = 0; 2021 2022if nargin == 0 2023 % get filename 2024 [edfname,edfpath]=uigetfile('*.*','Open EDF File'); 2025 Filename = [edfpath,edfname]; 2026 if edfname == 0 2027 return; 2028 end 2029end 2030 2031if 0, 2032%%% becomes obsolete 2033% variables to find things in the header 2034H1idx=[8 80 80 8 8 8 44 8 8 4]; 2035H2idx=[16 80 8 8 8 8 8 80 8 32]; 2036GDFTYP_BYTE=[1 1 1 2 2 4 4 8 8 4 8 0 0 0 0 0 4 8]'; 2037GDFTYPES=[0 1 2 3 4 5 6 7 16 17]; 2038 2039fid=fopen(Filename, 'r', 'ieee-le'); 2040if (fid < 0) 2041 errordlg('Error reading file', 'File Error'); 2042 return 2043end; 2044Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 2045numedf = length(Data.EDF) + 1; 2046 2047% read all data 2048EDFHead.FILE.FID = fid; 2049EDFHead.FILE.OPEN = 1; 2050EDFHead.FileName = Filename; 2051 2052PPos = min([max(find(Filename == '.')) length(Filename) + 1]); 2053SPos = max([0 find(Filename == filesep)]); 2054EDFHead.FILE.Ext = Filename(PPos+1:length(Filename)); 2055EDFHead.FILE.Name = Filename(SPos+1:PPos-1); 2056EDFHead.FILE.Path = edfpath; 2057 2058H1 = fread(EDFHead.FILE.FID,184,'uint8=>char')'; 2059EDFHead.VERSION = H1(1:8); % 8 Byte Versionsnummer 2060IsGDF = strcmp(EDFHead.VERSION(1:3), 'GDF'); 2061if (~strcmp(EDFHead.VERSION, '0 ') && ~IsGDF) 2062 errordlg('Unknown file version', 'File error'); 2063 return; 2064end 2065EDFHead.PID = deblank(H1(9:88)); % 80 Byte local patient identification 2066EDFHead.RID = deblank(H1(89:168)); % 80 Byte local recording identification 2067if IsGDF % handle different file formats 2068 EDFHead.T0 = [str2num(H1(168 + [1:4])) ... 2069 str2num(H1(168 + [5 6])) ... 2070 str2num(H1(168 + [7 8])) ... 2071 str2num(H1(168 + [9 10])) ... 2072 str2num(H1(168 + [11 12])) ... 2073 str2num(H1(168 + [13:16]))]; 2074 if str2num(EDFHead.VERSION(4:8)) < 0.12 2075 tmp = fread(EDFHead.FILE.FID, 8, 'uint8=>char')'; % header-length 2076 EDFHead.HeadLen = str2num(tmp); 2077 else 2078 EDFHead.HeadLen = fread(EDFHead.FILE.FID, 1, 'int64'); 2079 end 2080 tmp = fread(EDFHead.FILE.FID, 44, 'uchar'); % 44 bytes reserved 2081 EDFHead.NRec = fread(EDFHead.FILE.FID, 1, 'int64'); 2082 if strcmp(EDFHead.VERSION(4:8),' 0.10') 2083 EDFHead.Dur = fread(EDFHead.FILE.FID, 1, 'float64'); 2084 else 2085 tmp = fread(EDFHead.FILE.FID, 2, 'uint32'); 2086 EDFHead.Dur = tmp(1)./tmp(2); 2087 end 2088 EDFHead.NS = fread(EDFHead.FILE.FID, 1, 'uint32'); 2089else 2090 EDFHead.T0 = [str2num(H1(168+[7 8])) ... 2091 str2num(H1(168+[4 5])) ... 2092 str2num(H1(168+[1 2])) ... 2093 str2num(H1(168+[9 10])) ... 2094 str2num(H1(168+[12 13])) ... 2095 str2num(H1(168+[15 16])) ]; 2096 if EDFHead.T0(1) < 91 2097 EDFHead.T0(1) = 2000 + EDFHead.T0(1); 2098 elseif EDFHead.T0(1) < 100 2099 EDFHead.T0(1) = 1900 + EDFHead.T0(1); 2100 end 2101 H1(185:256) = fread(EDFHead.FILE.FID, 256-184, 'uint8=>char')'; 2102 EDFHead.HeadLen = str2num(H1(185:192)); % 8 Byte Length of Header 2103 EDFHead.NRec = str2num(H1(237:244)); % 8 Byte # of data records 2104 EDFHead.Dur = str2num(H1(245:252)); % 8 Byte # duration of data record in sec 2105 EDFHead.NS = str2num(H1(253:256)); % 8 Byte # of signals 2106end 2107 2108if ~IsGDF 2109 idx1 = cumsum([0 H2idx]); 2110 idx2 = EDFHead.NS * idx1; 2111 h2 = zeros(EDFHead.NS, 256); 2112 H2 = fread(EDFHead.FILE.FID, EDFHead.NS * 256, 'uint8=>char'); 2113 H2(H2==0) = 32; % set zero padded strings to blanks 2114 for k = 1:length(H2idx) 2115 h2(:, (idx1(k)+1):idx1(k+1)) = reshape(H2((idx2(k)+1):idx2(k+1)), ... 2116 H2idx(k), EDFHead.NS)'; 2117 end 2118 EDFHead.Label = h2(:, idx1(1)+1:idx1(2)); 2119 EDFHead.Transducer = h2(:, idx1(2)+1:idx1(3)); 2120 EDFHead.PhysDim = cellstr(h2(:, idx1(3)+1:idx1(4))); 2121 EDFHead.PhysMin = str2num(h2(:, idx1(4)+1:idx1(5))); 2122 EDFHead.PhysMax = str2num(h2(:, idx1(5)+1:idx1(6))); 2123 EDFHead.DigMin = str2num(h2(:, idx1(6)+1:idx1(7))); 2124 EDFHead.DigMax = str2num(h2(:, idx1(7)+1:idx1(8))); 2125 EDFHead.PreFilt = h2(:, idx1(8)+1:idx1(9)); 2126 EDFHead.SPR = str2num(h2(:, idx1(9)+1:idx1(10))); 2127 EDFHead.GDFTYP = 3*ones(1, EDFHead.NS); 2128else 2129 fseek(EDFHead.FILE.FID, 256, 'bof'); 2130 EDFHead.Label = fread(EDFHead.FILE.FID, [16,EDFHead.NS], 'uint8=>char')'; 2131 EDFHead.Transducer = fread(EDFHead.FILE.FID, [80,EDFHead.NS], 'uint8=>char')'; 2132 EDFHead.PhysDim = cellstr(fread(EDFHead.FILE.FID, [8,EDFHead.NS], 'uint8=>char')'); 2133 EDFHead.PhysMin = fread(EDFHead.FILE.FID, [EDFHead.NS,1], 'float64'); 2134 EDFHead.PhysMax = fread(EDFHead.FILE.FID, [EDFHead.NS,1], 'float64'); 2135 EDFHead.DigMin = fread(EDFHead.FILE.FID, [EDFHead.NS,1], 'int64'); 2136 EDFHead.DigMax = fread(EDFHead.FILE.FID, [EDFHead.NS,1], 'int64'); 2137 EDFHead.PreFilt = fread(EDFHead.FILE.FID, [80,EDFHead.NS], 'uint8=>char')'; 2138 EDFHead.SPR = fread(EDFHead.FILE.FID, [1,EDFHead.NS], 'uint32')'; 2139 EDFHead.GDFTYP = fread(EDFHead.FILE.FID, [1,EDFHead.NS], 'uint32'); 2140 tmp = (EDFHead.GDFTYP == 0); 2141 EDFHead.PhysMax(tmp) = 1; 2142 EDFHead.PhysMin(tmp) = 0; 2143 EDFHead.DigMax(tmp) = 1; 2144 EDFHead.DigMin(tmp) = 0; 2145end 2146 2147% check validity of DigMin and DigMax 2148if (length(EDFHead.DigMin) ~= EDFHead.NS) 2149 if ShowHeadErr 2150 waitfor(warndlg('Failing Digital Minimum', 'Open EDF file')); 2151 end 2152 EDFHead.DigMin = -(2^15) * ones(EDFHead.NS, 1); 2153end 2154if (length(EDFHead.DigMax) ~= EDFHead.NS) 2155 if ShowHeadErr 2156 waitfor(warndlg('Failing Digital Maximum', 'Open EDF file')); 2157 end 2158 EDFHead.DigMax = (2^15-1) * ones(EDFHead.NS, 1); 2159end 2160if (any(EDFHead.DigMin >= EDFHead.DigMax)) 2161 if ShowHeadErr 2162 waitfor(warndlg('Digital Minimum larger than Maximum', ['Open EDF' ... 2163 ' file'])); 2164 end 2165end 2166 2167% check validity of PhysMin and PhysMax 2168if (length(EDFHead.PhysMin) ~= EDFHead.NS) 2169 if ShowHeadErr 2170 waitfor(warndlg('EDFOPEN: Failing Physical Minimum', 'Open EDF file')); 2171 end 2172 EDFHead.PhysMin = EDFHead.DigMin; 2173end 2174if (length(EDFHead.PhysMax) ~= EDFHead.NS) 2175 if ShowHeadErr 2176 waitfor(warndlg('Warning EDFOPEN: Failing Physical Maximum', ['Open EDF' ... 2177 ' file'])); 2178 end 2179 EDFHead.PhysMax = EDFHead.DigMax; 2180end 2181if (any(EDFHead.PhysMin >= EDFHead.PhysMax)) 2182 if ShowHeadErr 2183 waitfor(warndlg('EDFOPEN: Physical Minimum larger than Maximum', ['Open' ... 2184 ' EDF file'])); 2185 end 2186 EDFHead.PhysMin = EDFHead.DigMin; 2187 EDFHead.PhysMax = EDFHead.DigMax; 2188end 2189 2190EDFHead.Cal = (EDFHead.PhysMax - EDFHead.PhysMin) ./ (EDFHead.DigMax - ... 2191 EDFHead.DigMin); 2192EDFHead.Off = EDFHead.PhysMin - EDFHead.Cal .* EDFHead.DigMin; 2193tmp = (EDFHead.Cal < 0); 2194EDFHead.Cal(tmp) = 1; 2195EDFHead.Off(tmp) = 0; 2196 2197EDFHead.Calib = [EDFHead.Off'; diag(EDFHead.Cal)]; 2198EDFHead.SampleRate = EDFHead.SPR / EDFHead.Dur; 2199 2200bi = [0; cumsum(EDFHead.SPR)]; 2201EDFHead.AS.spb = sum(EDFHead.SPR); 2202EDFHead.AS.bi = bi; 2203EDFHead.AS.bpb = sum(EDFHead.SPR .* GDFTYP_BYTE(EDFHead.GDFTYP+1)); 2204EDFHead.AS.GDFbi = [0; cumsum(EDFHead.AS.bpb)]; 2205 2206EDFHead.Chan_Select = (EDFHead.SPR == max(EDFHead.SPR)); 2207for k = 1:EDFHead.NS 2208 if EDFHead.Chan_Select(k) 2209 EDFHead.ChanTyp(k) = 'N'; 2210 else 2211 EDFHead.ChanTyp(k) = ' '; 2212 end; 2213 if findstr(upper(EDFHead.Label(k,:)), 'ECG') 2214 EDFHead.ChanTyp(k) = 'C'; 2215 elseif findstr(upper(EDFHead.Label(k,:)), 'EKG') 2216 EDFHead.ChanTyp(k) = 'C'; 2217 elseif findstr(upper(EDFHead.Label(k,:)), 'EEG') 2218 EDFHead.ChanTyp(k) = 'E'; 2219 elseif findstr(upper(EDFHead.Label(k,:)), 'EOG') 2220 EDFHead.ChanTyp(k) = 'O'; 2221 elseif findstr(upper(EDFHead.Label(k,:)), 'EMG') 2222 EDFHead.ChanTyp(k) = 'M'; 2223 elseif findstr(upper(EDFHead.Label(k,:)), 'RESP') 2224 EDFHead.ChanTyp(k) = 'R'; 2225 end 2226end 2227 2228fseek(EDFHead.FILE.FID, 32 * EDFHead.NS, 0); 2229if EDFHead.NRec == -1 % unknown record size, determine correct NRec 2230 fseek(EDFHead.FILE.FID, 0, 'eof'); 2231 endpos = ftell(EDFHead.FILE.FID); 2232 EDFHead.NRec = floor((endpos - EDFHead.HeadLen) / (sum(EDFHead.AS.bpb))); 2233end 2234fseek(EDFHead.FILE.FID, EDFHead.HeadLen, 'bof'); 2235else 2236 EDFHead = sopen(Filename,'r',0,'OVERFLOWDETECTION:OFF FORCEALLCHANNEL'); 2237 EDFHead.Dur = EDFHead.SPR/EDFHead.SampleRate; 2238 EDFHead.PhysDim = physicalunits(EDFHead.PhysDimCode); 2239 2240 Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 2241 numedf = length(Data.EDF) + 1; 2242end; 2243 2244Data.EDF(numedf).Head = EDFHead; 2245drawnow; 2246set(findobj('Tag', 'ViewEDFFigure'), 'UserData', Data); 2247LocalResetDisplay; 2248 2249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2250% LocalEDFRead 2251% read data from EDF file 2252function [Record, EDFHead] = LocalEDFRead(EDFHead, recinfo) 2253 2254startrec = recinfo(1); 2255numrec = recinfo(2); 2256 2257 2258if 0, 2259%%% obsolete ??? 2260 2261% define GDF data types 2262GDF_STRING = {'uchar', 'int8', 'uint8', 'int16', 'uint16', 'int32', ... 2263 'uint32', 'int64', 'uint64', '', '', '', '', '', '', '', 'float32', ... 2264 'float64'}; 2265 2266GDF_STRING{256+24} = 'bit24'; 2267GDF_STRING{512+24} = 'ubit24'; 2268 2269if LocalEDFSeek(EDFHead, startrec, 'bof') < 0 2270 if numrec ~= 0 2271 waitfor(warndlg('Can not seek start record', 'Read EDF data')); 2272 end 2273 Record = {}; 2274 return; 2275end 2276 2277LocalWatchOn; 2278 2279RecLen = max(EDFHead.SPR); 2280for rec = 1:numrec 2281 for ch = 1:EDFHead.NS 2282 [d, count] = fread(EDFHead.FILE.FID, EDFHead.AS.SPR(ch), ... 2283 GDF_STRING{EDFHead.GDFTYP(ch)+1}); 2284 if count < 1 2285 break; 2286 end 2287 S(EDFHead.AS.bi(ch)+1:EDFHead.AS.bi(ch+1), rec) = d; 2288 end 2289 if count < 1 2290 numrec = rec; 2291 waitfor(warndlg(sprintf('Can not read %i records', numrec), 'Read EDF data')); 2292 break 2293 end 2294end 2295 2296for ch = 1:EDFHead.NS 2297 S(EDFHead.AS.bi(ch)+1 : EDFHead.AS.bi(ch+1),:) = S(EDFHead.AS.bi(ch)+1 : ... 2298 EDFHead.AS.bi(ch+1),:) * EDFHead.Cal(ch) + EDFHead.Off(ch); 2299end 2300 2301for ch = 1:EDFHead.NS, 2302 Record{ch} = reshape(S(EDFHead.AS.bi(ch)+1 : EDFHead.AS.bi(ch+1),:), ... 2303 EDFHead.AS.SPR(ch) * numrec, 1); 2304end 2305EDFHead.AS.numrec = numrec; 2306EDFHead.AS.startrec = startrec; 2307LocalWatchOff; 2308 2309else 2310LocalWatchOn; 2311 2312 Dur = EDFHead.SPR/EDFHead.SampleRate; 2313 [s,EDFHead] = sread(EDFHead,numrec*Dur,startrec*Dur); 2314 for ch = 1:EDFHead.NS, 2315 Record{ch} = s(:,ch); 2316 end; 2317 2318LocalWatchOff; 2319end 2320 2321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2322% LocalEDFSeek 2323% change position in EDF file 2324function [status] = LocalEDFSeek(EDFHead, offset, origin) 2325if (origin == -1) || (origin == 'bof'), 2326 offset = EDFHead.HeadLen + EDFHead.AS.bpb * offset; 2327 status = fseek(EDFHead.FILE.FID, offset, origin); 2328elseif (origin == 0) || (origin == 'cof'), 2329 offset = EDFHead.AS.bpb * offset; 2330 status = fseek(EDFHead.FILE.FID, offset, origin); 2331elseif (origin == 1) || (origin == 'eof'), 2332 offset = EDFHead.HeadLen + EDFHead.AS.bpb * (EDFHead.NRec + offset); 2333 status = fseek(EDFHead.FILE.FID, offset, -1); 2334end; 2335 2336%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2337% LocalEDFClose 2338% close an EDF file 2339function LocalEDFClose() 2340Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 2341if length(Data.EDF)==0 2342 errordlg('No EDF-File is open!', 'Error'); 2343 return; 2344end 2345 2346[ind, cancelled] = LocalSelectEDFFile({'Close EDF file', 'Close file'}, Data.EDF); 2347if cancelled 2348 return 2349end 2350 2351%fclose(Data.EDF(ind).Head.FILE.FID); 2352sclose(Data.EDF(ind).Head); 2353 2354for i = ind:(length(Data.EDF)-1) 2355 Data.Display.EDF(i) = Data.Display.EDF(i+1); 2356 Data.EDF(i) = Data.EDF(i+1); 2357end 2358numedf = length(Data.EDF)-1; 2359if numedf == 0 2360 Data.EDF = []; 2361 Data.Display.EDF = []; 2362else 2363 Data.EDF = Data.EDF(1:numedf); 2364 Data.Display.EDF = Data.Display.EDF(1:numedf); 2365end 2366set(findobj('Tag', 'ViewEDFFigure'), 'UserData', Data); 2367% take care of plugins 2368if (length(Data.Plugin) > 0) 2369 waitfor(warndlg('All plugins using the closed EDF file will be removed', ... 2370 'Close warning')); 2371 for i = length(Data.Plugin):-1:1 2372 if (Data.Plugin(i).EDFFile == ind) 2373 LocalRemovePlugin(i); 2374 end 2375 end 2376end 2377LocalRepaint; 2378 2379 2380%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2381% LocalSelectEDFFile 2382% display dialog to select a loaded EDF file 2383function [FileNum, Cancelled] = LocalSelectEDFFile(Title, EDFData) 2384dlgh = dialog(... 2385 'Name', Title{1}, ... 2386 'CloseRequestFcn', 'set(gcf,''UserData'',''Cancel'');uiresume;'); 2387dlgpos = get(dlgh, 'Position'); 2388set(dlgh, 'Position', [dlgpos(1),dlgpos(2),300,100]); 2389 2390EDFNames = {}; 2391% get EDF FIle names 2392for i = 1:length(EDFData) 2393 EDFNames = {EDFNames{:}, EDFData(i).Head.FileName}; 2394end 2395 2396poph = uicontrol(dlgh, ... 2397 'Style', 'Popup', ... 2398 'Units', 'Normalized', ... 2399 'String',EDFNames, ... 2400 'Value', 1, ... 2401 'Position', [0.05, 0.5, 0.9, 0.35]); 2402% buttons 2403uicontrol(dlgh, ... 2404 'Style', 'PushButton', ... 2405 'Units', 'Normalized', ... 2406 'String', Title{2}, ... 2407 'Position', [0.1, 0.05, 0.3, 0.3], ... 2408 'Callback', 'set(gco,''UserData'',''OK'');uiresume;'); 2409uicontrol(dlgh, ... 2410 'Style', 'PushButton', ... 2411 'Units', 'Normalized', ... 2412 'String', 'Cancel', ... 2413 'Position', [0.6, 0.05, 0.3, 0.3], ... 2414 'Callback', 'set(gco,''UserData'',''Cancel'');uiresume;'); 2415 2416drawnow; 2417uiwait(dlgh); 2418if strcmp(get(gco,'UserData'),'OK') 2419 Cancelled = 0; 2420 FileNum = get(poph, 'Value'); 2421else 2422 Cancelled = 1; 2423 FileNum = 0; 2424end 2425delete(dlgh); 2426 2427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2428% LocalCloseViewEDF 2429% close viewer 2430function LocalCloseViewEDF() 2431Data = get(findobj('Tag', 'ViewEDFFigure'), 'UserData'); 2432% close all files 2433for i = 1:length(Data.EDF); 2434 %fclose(Data.EDF(i).Head.FILE.FID); 2435 sclose(Data.EDF(i).Head); 2436end 2437delete(findobj('Tag', 'ViewEDFFigure')); 2438