PageRenderTime 87ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/dummymri/DummyMriMain.PAS

http://dccn-lab.googlecode.com/
Pascal | 434 lines | 334 code | 55 blank | 45 comment | 17 complexity | 7d7c278059b37ae453316a043fa240c4 MD5 | raw file
  1. unit DummyMriMain;
  2. //
  3. // DummyMRI
  4. //
  5. // The Dummy MRI application allows playback of a wav sound file associated with
  6. // one single TR of an accociated sequence at the MRI Avanto or Trio.
  7. // No actual MRI sequence parameters can be adjusted (the wav soundfile should just
  8. // generate the proper sound for each TR.
  9. //
  10. // Only TR and measurements can be set to allow emulation of the measurement time
  11. // and number of scanned volumes
  12. //
  13. // For each volume a scan trigger pulse is generated via the attached BITSI box
  14. // For each volume a wav sound file is played, emulating the scanner noise in the pace
  15. // of TR.
  16. //
  17. // Note: If the playback time of the sound file is longer than the TR, the soundfile
  18. // is stopped, rewinded and replayed at the beginning of the next TR. This results
  19. // in an uninterrupted playback of the sound file. In such case the subject would
  20. // only hear the first TR-time segments of the complete sound file.
  21. //
  22. // Version history:
  23. //
  24. // Created version 1.1: May 10, 2010, Erik van den Boogert
  25. // Debugged version 1.2: May 11, 2010, Erik van den Boogert
  26. //
  27. interface
  28. uses Windows, Classes, Graphics, Forms, Controls, Menus,
  29. Dialogs, StdCtrls, Buttons, ExtCtrls, ComCtrls, ImgList, StdActns,
  30. ActnList, ToolWin, OoMisc, AdPort, MPlayer, Spin, SysUtils, IniFiles;
  31. type
  32. TSDIAppForm = class(TForm)
  33. OpenDialog: TOpenDialog;
  34. SaveDialog: TSaveDialog;
  35. ToolBar1: TToolBar;
  36. ToolButton1: TToolButton;
  37. ToolButton2: TToolButton;
  38. ActionList1: TActionList;
  39. FileNew1: TAction;
  40. FileOpen1: TAction;
  41. FileSave1: TAction;
  42. FileSaveAs1: TAction;
  43. FileExit1: TAction;
  44. EditCut1: TEditCut;
  45. EditCopy1: TEditCopy;
  46. EditPaste1: TEditPaste;
  47. HelpAbout1: TAction;
  48. StatusBar: TStatusBar;
  49. ImageList1: TImageList;
  50. MainMenu1: TMainMenu;
  51. File1: TMenuItem;
  52. FileOpenItem: TMenuItem;
  53. FileSaveItem: TMenuItem;
  54. FileSaveAsItem: TMenuItem;
  55. N1: TMenuItem;
  56. FileExitItem: TMenuItem;
  57. Help1: TMenuItem;
  58. HelpAboutItem: TMenuItem;
  59. comBITSI: TApdComPort;
  60. TimerRunMRI: TTimer;
  61. mpSound: TMediaPlayer;
  62. btnStartStop: TButton;
  63. lblTS: TLabel;
  64. lblTA: TLabel;
  65. panRoutine: TPanel;
  66. lblSoundFile: TLabel;
  67. lblComNumber: TLabel;
  68. edtComNumber: TSpinEdit;
  69. lblTR: TLabel;
  70. edtTR: TSpinEdit;
  71. lblMeasurements: TLabel;
  72. edtMeasurements: TSpinEdit;
  73. shpLineLeft1: TShape;
  74. shpLineRight: TShape;
  75. lblTRUnits: TLabel;
  76. shpLineLeft2: TShape;
  77. Shape4: TShape;
  78. TimerDisplay: TTimer;
  79. edtSoundFile: TEdit;
  80. chkPlaySoundFile: TCheckBox;
  81. OpenDialogSoundFile: TOpenDialog;
  82. btnBrowse: TButton;
  83. lblSoundFilePath: TLabel;
  84. procedure FileOpen1Execute(Sender: TObject);
  85. procedure FileSave1Execute(Sender: TObject);
  86. procedure FileExit1Execute(Sender: TObject);
  87. procedure HelpAbout1Execute(Sender: TObject);
  88. procedure TimerRunMRITimer(Sender: TObject);
  89. procedure edtSlicesChange(Sender: TObject);
  90. procedure edtTRChange(Sender: TObject);
  91. procedure edtMeasurementsChange(Sender: TObject);
  92. procedure edtConcatenationsChange(Sender: TObject);
  93. procedure btnStartStopClick(Sender: TObject);
  94. procedure TimerDisplayTimer(Sender: TObject);
  95. procedure FormCreate(Sender: TObject);
  96. procedure btnBrowseClick(Sender: TObject);
  97. private
  98. { Private declarations }
  99. TAms : longint;
  100. TSms : longint;
  101. Time32Started: LongWord;
  102. MeasurementsCount: longint;
  103. DragInProgress : boolean;
  104. procedure UpdateTA;
  105. procedure UpdateTS;
  106. procedure OnChangeProtocolParam;
  107. procedure EnableEditing;
  108. procedure DisableEditing;
  109. procedure SendBITSITrigger;
  110. procedure PlayMRISound;
  111. procedure CloseComBITSI;
  112. procedure OpenComBITSI;
  113. procedure SaveInifile(IniFileName: string);
  114. procedure LoadInifile(IniFileName: string);
  115. public
  116. { Public declarations }
  117. end;
  118. var
  119. SDIAppForm: TSDIAppForm;
  120. implementation
  121. uses about;
  122. {$R *.dfm}
  123. //--- Time format methods ------------------------------------------------------
  124. Function RelTimeToStr(RelTime:Real): String;
  125. const
  126. RErr = 0.00003;
  127. var
  128. DPara,
  129. Min, Sec,
  130. RelTmInt : Integer;
  131. MinStr, SecStr : string[3];
  132. FullTmStr : string[11];
  133. begin
  134. Str((RelTime + 10000 + RErr):5:2, FullTmStr);
  135. Val(Copy(FullTmStr,2,4), RelTmInt, DPara);
  136. Min := (RelTmInt div 60) + 100; Str(Min:3, MinStr);
  137. Sec := (RelTmInt mod 60) + 100; Str(Sec:3, SecStr);
  138. Result := Copy(MinStr,2,2)+':'+Copy(SecStr,2,2); //+Copy(FullTmStr,6,3);
  139. end;
  140. Function GetPCTime32:LongWord;
  141. begin
  142. Result := DateTimeToTimeStamp(Time).Time;
  143. end;
  144. Function ExtractFileName(FileName: string): string;
  145. begin
  146. Result := FileName;
  147. While (Pos('\',Result) > 0) do
  148. Result := Copy(Result,Pos('\',Result)+1,255);
  149. end;
  150. //--- Load & Save inifiles -----------------------------------------------------
  151. procedure TSDIAppForm.SaveInifile(IniFileName: string);
  152. var
  153. IniFile: TIniFile;
  154. begin
  155. try
  156. IniFile := TIniFile.Create(IniFileName);
  157. IniFile.WriteString('DummyMRI','SoundFile', edtSoundFile.Text);
  158. IniFile.WriteString('DummyMRI','SoundFilePath', lblSoundFilePath.Caption);
  159. IniFile.WriteInteger('DummyMRI','TR', edtTR.Value);
  160. IniFile.WriteInteger('DummyMRI','Measurements', edtMeasurements.Value);
  161. IniFile.WriteBool('DummyMRI','PlaySoundFile', chkPlaySoundFile.checked);
  162. IniFile.WriteInteger('DummyMRI','BITSIComPort', edtComNumber.Value);
  163. IniFile.Free;
  164. except
  165. IniFile.Free;
  166. ShowMessage('Error: Saving settings failed.')
  167. end;
  168. end;
  169. procedure TSDIAppForm.LoadInifile(IniFileName: string);
  170. var
  171. IniFile: TIniFile;
  172. begin
  173. try
  174. IniFile := TIniFile.Create(IniFileName);
  175. edtSoundFile.text := IniFile.ReadString('DummyMRI','SoundFile', 'myMRISound.wav');
  176. lblSoundFilePath.caption := IniFile.ReadString('DummyMRI','SoundFilePath', 'myMRISound.wav');
  177. edtTR.Value := IniFile.ReadInteger('DummyMRI','TR', 2000);
  178. edtMeasurements.Value := IniFile.ReadInteger('DummyMRI','Measurements', 100);
  179. chkPlaySoundFile.checked := IniFile.ReadBool('DummyMRI','PlaySoundFile', false);
  180. edtComNumber.Value := IniFile.ReadInteger('DummyMRI','BITSIComPort', 1);
  181. IniFile.Free;
  182. if NOT FileExists(lblSoundFilePath.Caption) then
  183. begin
  184. chkPlaySoundFile.checked := false;
  185. ShowMessage('Warning: Sound file not found, sound playback disabled.');
  186. end;
  187. except
  188. IniFile.Free;
  189. ShowMessage('Error: Loading settings failed.');
  190. end;
  191. end;
  192. procedure TSDIAppForm.FileOpen1Execute(Sender: TObject);
  193. begin
  194. if edtTR.Enabled then
  195. begin
  196. if OpenDialog.Execute then LoadIniFile(OpenDialog.FileName);
  197. end;
  198. end;
  199. procedure TSDIAppForm.FileSave1Execute(Sender: TObject);
  200. begin
  201. if edtTR.Enabled then
  202. begin
  203. if SaveDialog.Execute then SaveIniFile(SaveDialog.FileName);
  204. end;
  205. end;
  206. //--- Create, Close en About methods -------------------------------------------
  207. procedure TSDIAppForm.FormCreate(Sender: TObject);
  208. begin
  209. OpenComBITSI;
  210. SendBITSITrigger;
  211. end;
  212. procedure TSDIAppForm.FileExit1Execute(Sender: TObject);
  213. begin
  214. Close;
  215. end;
  216. procedure TSDIAppForm.HelpAbout1Execute(Sender: TObject);
  217. begin
  218. AboutBox.ShowModal;
  219. end;
  220. //--- BITSI ComPort methods ----------------------------------------------------
  221. procedure TSDIAppForm.btnBrowseClick(Sender: TObject);
  222. begin
  223. if OpenDialogSoundFile.execute then
  224. begin
  225. lblSoundFilePath.Caption := OpenDialogSoundFile.FileName;
  226. edtSoundFile.Text := ExtractFileName(lblSoundFilePath.Caption);
  227. end;
  228. end;
  229. procedure TSDIAppForm.CloseComBITSI;
  230. begin
  231. try comBITSI.Open := false; except end;
  232. end;
  233. procedure TSDIAppForm.OpenComBITSI;
  234. begin
  235. comBITSI.ComNumber := edtComNumber.Value;
  236. try
  237. comBITSI.Open := true;
  238. except
  239. ShowMessage('Error: BITSI Com-Port '+ IntToStr(edtComNumber.Value) +' could not be opened');
  240. end;
  241. end;
  242. procedure TSDIAppForm.SendBITSITrigger;
  243. begin
  244. try
  245. comBITSI.PutChar(Chr(1));
  246. except end;
  247. end;
  248. //--- mpSound methods ----------------------------------------------------------
  249. procedure TSDIAppForm.PlayMRISound;
  250. begin
  251. try
  252. mpSound.Stop;
  253. mpSound.Rewind;
  254. mpSound.Play;
  255. except end;
  256. end;
  257. //--- Update TA & TA labels ----------------------------------------------------
  258. procedure TSDIAppForm.UpdateTA;
  259. begin
  260. TAms := edtMeasurements.value * edtTR.value;
  261. lblTA.Caption := 'TA: ' + RelTimeToStr(TAms/1000);
  262. end;
  263. procedure TSDIAppForm.UpdateTS;
  264. begin
  265. //--- initialize TS = TA
  266. TSms := TAms;
  267. //--- only when running count down residual time using GetPCTime32
  268. if btnStartStop.Caption = 'Stop' then TSms := TAms - (GetPCTime32 - Time32Started);
  269. //--- ensure TS doesn't underrun 0 s.
  270. if (TSms < 0) then TSms := 0;
  271. lblTS.Caption := 'Scanning: ' + RelTimeToStr(TSms/1000);
  272. end;
  273. procedure TSDIAppForm.OnChangeProtocolParam;
  274. begin
  275. UpdateTA;
  276. end;
  277. procedure TSDIAppForm.TimerDisplayTimer(Sender: TObject);
  278. begin
  279. UpdateTA;
  280. UpdateTS;
  281. end;
  282. procedure TSDIAppForm.edtMeasurementsChange(Sender: TObject);
  283. begin
  284. OnChangeProtocolParam;
  285. end;
  286. procedure TSDIAppForm.edtConcatenationsChange(Sender: TObject);
  287. begin
  288. OnChangeProtocolParam;
  289. end;
  290. procedure TSDIAppForm.edtSlicesChange(Sender: TObject);
  291. begin
  292. OnChangeProtocolParam;
  293. end;
  294. procedure TSDIAppForm.edtTRChange(Sender: TObject);
  295. begin
  296. OnChangeProtocolParam;
  297. end;
  298. //--- Prepare, Start & Stop methods --------------------------------------------
  299. procedure TSDIAppForm.DisableEditing;
  300. begin
  301. edtMeasurements.Enabled := false;
  302. edtTR.Enabled := false;
  303. edtComNumber.Enabled := false;
  304. chkPlaySoundFile.Enabled := false;
  305. end;
  306. procedure TSDIAppForm.EnableEditing;
  307. begin
  308. edtMeasurements.Enabled := true;
  309. edtTR.Enabled := true;
  310. edtComNumber.Enabled := true;
  311. chkPlaySoundFile.Enabled := true;
  312. end;
  313. procedure TSDIAppForm.btnStartStopClick(Sender: TObject);
  314. begin
  315. //--- Case Prepare
  316. if btnStartStop.Caption = 'Prepare' then
  317. begin
  318. if comBITSI.ComNumber <> edtComNumber.Value then
  319. begin
  320. CloseComBITSI;
  321. OpenComBITSI;
  322. end;
  323. //
  324. if NOT FileExists(lblSoundFilePath.Caption) then
  325. begin
  326. chkPlaySoundFile.checked := false;
  327. ShowMessage('Warning: Sound File does not exist, sound playback disabled');
  328. end;
  329. //
  330. if (chkPlaySoundFile.checked) then
  331. begin
  332. mpSound.Close;
  333. mpSound.FileName := lblSoundFilePath.Caption;
  334. try mpSound.Open;
  335. except
  336. chkPlaySoundFile.checked := false;
  337. ShowMessage('Error: Sound File could not be loaded, sound playback disabled.');
  338. end;
  339. end;
  340. //
  341. if comBITSI.Open then
  342. begin
  343. DisableEditing;
  344. btnStartStop.Caption := 'Start';
  345. end;
  346. end else
  347. //--- Case Start
  348. if btnStartStop.Caption = 'Start' then
  349. begin
  350. Time32Started := GetPCTime32;
  351. MeasurementsCount := edtMeasurements.Value;
  352. DisableEditing;
  353. timerRunMRI.Interval := edtTR.Value;
  354. timerRunMRI.Enabled := true;
  355. SendBITSITrigger;
  356. if chkPlaySoundFile.checked then PlayMRISound;
  357. btnStartStop.Caption := 'Stop';
  358. end else
  359. //--- Case Stop
  360. begin
  361. EnableEditing;
  362. timerRunMRI.Enabled := false;
  363. btnStartStop.Caption := 'Prepare';
  364. end;
  365. end;
  366. //--- Timer loop running the MRI sequence --------------------------------------
  367. procedure TSDIAppForm.TimerRunMRITimer(Sender: TObject);
  368. begin
  369. Dec(MeasurementsCount);
  370. if (MeasurementsCount <= 0) then
  371. begin
  372. btnStartStopClick(Sender);
  373. end else
  374. begin
  375. SendBITSITrigger;
  376. if chkPlaySoundFile.checked then PlayMRISound;
  377. end;
  378. end;
  379. end.