saveNSx.m 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. function saveNSx(NSx,varargin)
  2. %%
  3. % Save an .NSx file from an NSx structure (gained by using openNSx)
  4. % Works with file spec 2.3
  5. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6. % Use: saveNSx(NSx,optionalinputarguments)
  7. % NSx: The NSx data structure.
  8. % All arguments below are optional:
  9. % Filename: A complete filepath for the output file.
  10. % Default: CurrentFilename-Modified.NSx
  11. %saveNSx version = '1.0.0.0';
  12. %%
  13. % Verify FilePath and establish overwrite paramaters
  14. if not(isempty(varargin))
  15. FilePath = varargin{1};
  16. else
  17. FilePath = [fullfile(NSx.MetaTags.FilePath,NSx.MetaTags.Filename) NSx.MetaTags.FileExt];
  18. [File,Path] = uiputfile;
  19. FilePath = [fullfile(Path,NSx.MetaTags.Filename(1:end)),'-modified', NSx.MetaTags.FileExt];
  20. end
  21. disp('This script will save a new file with the proper .NSx extensions');
  22. disp('but you should retain the previous file. Do you acknowledge the');
  23. Accept = input('risk inherent in saving modified versions of data files? (Y/N)','s');
  24. if strcmpi(Accept,'y')
  25. else
  26. disp('Ending Script...');
  27. return
  28. end
  29. %%
  30. % Write the basic header into the file
  31. %FullFile
  32. Debug = 1;
  33. if exist(FilePath)
  34. if exist(FilePath)
  35. disp('File already exists!');
  36. OverwritePrompt = input('Would you like to overwrite? (Y/N)','s');
  37. if strcmpi(OverwritePrompt,'y')
  38. Overwrite = 1;
  39. delete(FilePath);
  40. else
  41. return
  42. end
  43. end
  44. end
  45. clear Overwrite
  46. clear OverwritePrompt
  47. clear varargin
  48. %PausedFile?
  49. if iscell(NSx.Data)
  50. Paused = 1;
  51. NumberOfSegments = length(NSx.Data);
  52. else
  53. Paused = 0;
  54. end
  55. FileID = fopen(FilePath, 'w', 'ieee-le');
  56. %Basic header stuff
  57. BytesInBasicHeader = 8+2+4+16+256+4+4+16+4;
  58. BytesInExtendedHeader = 2+2+16+1+1+2+2+2+2+16+4+4+2+4+4+2;
  59. if Paused == 1
  60. for SegmentCount = 1:NumberOfSegments
  61. [NumberOfChannels,LengthOfData{SegmentCount}] = size(NSx.Data{SegmentCount});
  62. end
  63. elseif Paused == 0
  64. [NumberOfChannels,LengthOfData] = size(NSx.Data);
  65. end
  66. %File Type ID
  67. Before = 0;
  68. fwrite(FileID,NSx.MetaTags.FileTypeID(1:8));
  69. After = ftell(FileID);
  70. if After-Before ~= 8 && Debug == 1
  71. disp('error FildID')
  72. end
  73. %File spec
  74. Before = ftell(FileID);
  75. fwrite(FileID, [str2double(NSx.MetaTags.FileSpec(1)) str2double(NSx.MetaTags.FileSpec(3))], 'uint8');
  76. After = ftell(FileID);
  77. if After-Before ~= 2 && Debug == 1
  78. disp('error File Spec')
  79. end
  80. %Bytes in Headers
  81. Before = ftell(FileID);
  82. fwrite(FileID, BytesInBasicHeader+NumberOfChannels*BytesInExtendedHeader,'uint32');
  83. After = ftell(FileID);
  84. if After-Before ~= 4 && Debug == 1
  85. disp('error BytesInHeaders')
  86. end
  87. %Label
  88. Before = ftell(FileID);
  89. fwrite(FileID, NSx.MetaTags.SamplingLabel);
  90. After = ftell(FileID);
  91. if After-Before ~= 16 && Debug == 1
  92. disp('error label')
  93. end
  94. %Comment
  95. Before = ftell(FileID);
  96. if ~isempty(NSx.MetaTags.Comment)
  97. fwrite(FileID, NSx.MetaTags.Comment);
  98. else
  99. fwrite(FileID, repmat(' ', 1, 256));
  100. end
  101. After = ftell(FileID);
  102. if After-Before ~= 256 && Debug == 1
  103. disp('error comment')
  104. end
  105. %Period
  106. Before = ftell(FileID);
  107. fwrite(FileID, (1/NSx.MetaTags.SamplingFreq)*30000, 'uint32');
  108. After = ftell(FileID);
  109. if After-Before ~= 4 && Debug == 1
  110. disp('error period')
  111. end
  112. %Time Resolution of time stamps
  113. Before = ftell(FileID);
  114. fwrite(FileID, NSx.MetaTags.TimeRes,'uint32');
  115. After = ftell(FileID);
  116. if After-Before ~= 4 && Debug == 1
  117. disp('error time resolution')
  118. end
  119. %Time Origin
  120. Before = ftell(FileID);
  121. if ~isempty(NSx.MetaTags.DateTimeRaw)
  122. fwrite(FileID, NSx.MetaTags.DateTimeRaw,'uint16');
  123. else
  124. fwrite(FileID, [1900 1 1 0 0 0 0 0],'uint16');
  125. end
  126. After = ftell(FileID);
  127. if After-Before ~= 16 && Debug == 1
  128. disp('error Time Origin')
  129. end
  130. %Channel Count
  131. Before = ftell(FileID);
  132. fwrite(FileID, NumberOfChannels,'uint32');
  133. After = ftell(FileID);
  134. if After-Before ~= 4 && Debug == 1
  135. disp('error Channel Count')
  136. end
  137. %Extended header stuff
  138. %Number of these equal to number of channels
  139. for i = 1:NumberOfChannels
  140. % Type
  141. Before = ftell(FileID);
  142. fwrite(FileID, 'CC');
  143. After = ftell(FileID);
  144. if After-Before ~= 2 && Debug == 1
  145. disp('error Type')
  146. end
  147. % ElectrodeID
  148. Before = ftell(FileID);
  149. try
  150. fwrite(FileID, NSx.ElectrodesInfo(i).ElectrodeID,'uint16');
  151. catch
  152. fwrite(FileID, i,'uint16');
  153. end
  154. After = ftell(FileID);
  155. if After-Before ~= 2 && Debug == 1
  156. disp('error ElectrodeID')
  157. end
  158. % Electrode label
  159. Before = ftell(FileID);
  160. try
  161. fwrite(FileID, NSx.ElectrodesInfo(i).Label);
  162. catch
  163. templabel = ['chan' num2str(i) ' '];
  164. templabel(17:end) = [];
  165. fwrite(FileID, templabel);
  166. end
  167. After = ftell(FileID);
  168. if After-Before ~= 16 && Debug == 1
  169. disp('error Electrode Label')
  170. end
  171. % Physical connector
  172. Before = ftell(FileID);
  173. try
  174. fwrite(FileID, NSx.ElectrodesInfo(i).ConnectorBank, 'uint8');
  175. catch
  176. if i > 0 && i <= 32
  177. fwrite(FileID, 1, 'uint8');
  178. elseif i > 32 && i <= 64
  179. fwrite(FileID, 2, 'uint8');
  180. elseif i > 64 && i <= 96
  181. fwrite(FileID, 3, 'uint8');
  182. elseif i > 96 && i <= 128
  183. fwrite(FileID, 4, 'uint8');
  184. end
  185. end
  186. After = ftell(FileID);
  187. if After-Before ~= 1 && Debug == 1
  188. disp('error Physical Connector')
  189. end
  190. %Physical pin
  191. Before = ftell(FileID);
  192. try
  193. fwrite(FileID, NSx.ElectrodesInfo(i).ConnectorPin, 'uint8');
  194. catch
  195. fwrite(FileID, int2str((i-floor(i/32)*32)), 'uint8');
  196. end
  197. After = ftell(FileID);
  198. if After-Before ~= 1 && Debug == 1
  199. disp('error Physical Pin')
  200. end
  201. %Min Digital Value
  202. Before = ftell(FileID);
  203. try
  204. fwrite(FileID, NSx.ElectrodesInfo(i).MinDigiValue,'int16');
  205. catch
  206. fwrite(FileID, -32764,'int16');
  207. end
  208. After = ftell(FileID);
  209. if After-Before ~= 2 && Debug == 1
  210. disp('error min Digital Value')
  211. end
  212. %Max Digital Value
  213. Before = ftell(FileID);
  214. try
  215. fwrite(FileID, NSx.ElectrodesInfo(i).MaxDigiValue,'int16');
  216. catch
  217. fwrite(FileID, 32764,'int16');
  218. end
  219. After = ftell(FileID);
  220. if After-Before ~= 2 && Debug == 1
  221. disp('error Max Digital value')
  222. end
  223. %Min Analog Value
  224. Before = ftell(FileID);
  225. try
  226. fwrite(FileID, NSx.ElectrodesInfo(i).MinAnalogValue,'int16');
  227. catch
  228. fwrite(FileID, -8191,'int16');
  229. end
  230. After = ftell(FileID);
  231. if After-Before ~= 2 && Debug == 1
  232. disp('error Min Analog Value')
  233. end
  234. %Max Analog Value
  235. Before = ftell(FileID);
  236. try
  237. fwrite(FileID, NSx.ElectrodesInfo(i).MaxAnalogValue,'int16');
  238. catch
  239. fwrite(FileID, 8191,'int16');
  240. end
  241. After = ftell(FileID);
  242. if After-Before ~= 2 && Debug == 1
  243. disp('error Max Aanalog value')
  244. end
  245. %Units
  246. Before = ftell(FileID);
  247. try
  248. fwrite(FileID, NSx.ElectrodesInfo(i).AnalogUnits,'char');
  249. catch
  250. fwrite(FileID, 'uv ');
  251. end
  252. After = ftell(FileID);
  253. if After-Before ~= 16 && Debug == 1
  254. disp('error Units')
  255. end
  256. %High Freq Corner (High frequency cutoff in mHz)
  257. Before = ftell(FileID);
  258. try
  259. fwrite(FileID, NSx.ElectrodesInfo(i).HighFreqCorner,'uint32');
  260. catch
  261. fwrite(FileID, 0,'uint32');
  262. end
  263. After = ftell(FileID);
  264. if After-Before ~= 4 && Debug == 1
  265. disp('error High Corner')
  266. end
  267. %High Freq Order (Order of the filter used)
  268. Before = ftell(FileID);
  269. try
  270. fwrite(FileID, NSx.ElectrodesInfo(i).HighFreqOrder,'uint32');
  271. catch
  272. fwrite(FileID, 0,'uint32');
  273. end
  274. After = ftell(FileID);
  275. if After-Before ~= 4 && Debug == 1
  276. disp('error high Order')
  277. end
  278. %High Filter Type (0 = none, 1 = butterworth)
  279. Before = ftell(FileID);
  280. try
  281. fwrite(FileID, NSx.ElectrodesInfo(i).HighFilterType,'uint16');
  282. catch
  283. fwrite(FileID, 0,'uint16');
  284. end
  285. After = ftell(FileID);
  286. if After-Before ~= 2 && Debug == 1
  287. disp('error High Type')
  288. end
  289. %Low Freq Corner (Low frequency cutoff in mHz)
  290. Before = ftell(FileID);
  291. try
  292. fwrite(FileID, NSx.ElectrodesInfo(i).LowFreqCorner,'uint32');
  293. catch
  294. fwrite(FileID, 0,'uint32');
  295. end
  296. After = ftell(FileID);
  297. if After-Before ~= 4 && Debug == 1
  298. disp('error Low Corner')
  299. end
  300. %Low Freq Order (0 = none)
  301. Before = ftell(FileID);
  302. try
  303. fwrite(FileID, NSx.ElectrodesInfo(i).LowFreqOrder,'uint32');
  304. catch
  305. fwrite(FileID, 0,'uint32');
  306. end
  307. After = ftell(FileID);
  308. if After-Before ~= 4 && Debug == 1
  309. disp('error Low Order')
  310. end
  311. %Low Filter Type (0 = none, 1 = butterworth)
  312. Before = ftell(FileID);
  313. try
  314. fwrite(FileID, NSx.ElectrodesInfo(i).LowFilterType,'uint16');
  315. catch
  316. fwrite(FileID, 0,'uint16');
  317. end
  318. After = ftell(FileID);
  319. if After-Before ~= 2 && Debug == 1
  320. disp('error Low Type')
  321. end
  322. end
  323. %DataPackets
  324. if Paused == 0
  325. %Header
  326. fwrite(FileID, NSx.RawData.DataHeader(1));
  327. %Timestamp
  328. fwrite(FileID, NSx.MetaTags.Timestamp,'uint32');
  329. %Number of data points
  330. fwrite(FileID, LengthOfData, 'uint32');
  331. TotalDataPoints = LengthOfData * NumberOfChannels;
  332. %for i = 1:TotalDataPoints
  333. %Data points
  334. %fwrite(FileID, NSx.Data(i),'int16');
  335. fwrite(FileID, NSx.Data,'int16');
  336. %end
  337. elseif Paused == 1
  338. for SegmentNumber = 1:NumberOfSegments
  339. %Header
  340. fwrite(FileID, NSx.RawData.DataHeader(1+9*(SegmentNumber-1)));
  341. %Timestamp
  342. fwrite(FileID, NSx.MetaTags.Timestamp(SegmentNumber),'uint32');
  343. %Number of data points
  344. fwrite(FileID, LengthOfData{SegmentNumber}, 'uint32');
  345. TotalDataPoints = LengthOfData{SegmentNumber} * NumberOfChannels;
  346. %for i = 1:TotalDataPoints
  347. %Data points
  348. %fwrite(FileID, NSx.Data(i),'int16');
  349. fwrite(FileID, NSx.Data{SegmentNumber},'int16');
  350. %end
  351. end
  352. end
  353. fclose(FileID);