splitNSxNTrode.m 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. function splitNSxNTrode
  2. % splitNSxNTrode
  3. %
  4. % Opens and splits an NSx file based on its NTrode groups. It depends on
  5. % openCCF file.
  6. %
  7. % Use splitNSxNTrode
  8. %
  9. % This function does not take any inputs.
  10. %
  11. % Example 1:
  12. % splitNSxNTrode;
  13. %
  14. % In the example above, the user will be prompted to select a CCF file
  15. % first. The CCF contains the ntrode grouping infromation. Then the user
  16. % will be prompted to select a NSx file. The script will then split the
  17. % NSx file into smaller NSx files containing channels in given ntrode
  18. % groups. For example, if ntrode group one consists of channels 1,3,5,
  19. % and 12, then using splitNSxNTrode will split the file into a smaller
  20. % NSx file that contains those channels only. If there are multiple
  21. % ntrodes then the files will split into multiple smaller files, equal in
  22. % number of the ntrode groups.
  23. %
  24. % Kian Torab
  25. % ktorab@blackrockmicro.com
  26. % Blackrock Microsystems
  27. % Version 1.0.1.0
  28. %
  29. % Validating input parameter
  30. ccf = openCCF;
  31. splitCount = length(ccf.NTrodeInfo.NTrodeID);
  32. % Getting the file name
  33. if ~ismac
  34. [fname, path] = getFile('*.ns*', 'Choose an NSx file...');
  35. else
  36. [fname, path] = getFile('*.*', 'Choose an NSx file...');
  37. end
  38. if fname == 0
  39. disp('No file was selected.');
  40. if nargout
  41. clear variables;
  42. end
  43. return;
  44. end
  45. fext = fname(end-3:end);
  46. % Loading the file
  47. %% Reading Basic Header from file into NSx structure.
  48. FID = fopen([path fname], 'r', 'ieee-le');
  49. NSx.MetaTags.Filename = fname;
  50. NSx.MetaTags.FilePath = path(1:end-1);
  51. NSx.MetaTags.FileExt = fext;
  52. NSx.MetaTags.FileTypeID = fread(FID, [1,8] , '*char');
  53. disp(['Splitting the NSx file in ' num2str(splitCount) ' pieces...']);
  54. if strcmpi(NSx.MetaTags.FileTypeID, 'NEURALSG')
  55. disp('File type 2.1 is not yet implemented.');
  56. %NOT IMPLEMENTED YET
  57. % fseek(FID, 0, 'bof');
  58. % header = fread(FID, 314,'*uint8');
  59. % positionEOH = ftell(FID);
  60. % fseek(FID, 0, 'eof');
  61. % positionEOD = ftell(FID);
  62. % dataLength = positionEOD - positionEOH;
  63. % fseek(FID, 28, 'bof');
  64. % channelCount = fread(FID, 1 , 'uint32=>double');
  65. elseif strcmpi(NSx.MetaTags.FileTypeID, 'NEURALCD')
  66. % Calculating different points in the file
  67. fseek(FID, 0, 'bof');
  68. basicHeader = fread(FID, 314, '*uint8');
  69. positionEOB = ftell(FID);
  70. positionEOE = typecast(basicHeader(11:14), 'uint32');
  71. fseek(FID, 0, 'eof');
  72. positionEOD = ftell(FID);
  73. % Calculating channelCount, data Length
  74. channelCount = typecast(basicHeader(311:314), 'uint32');
  75. dataLength = positionEOD - positionEOE - 9;
  76. % Reading extended header and calculating channel IDs
  77. fseek(FID, positionEOB, 'bof');
  78. extHeader = fread(FID, [(positionEOE-positionEOB)/channelCount, channelCount], '*uint8');
  79. % Reading the channel IDs. This only wokrs for as long as channel IDs
  80. % are 8-bit integers. If they change, a typecast of 3:4 is necessasry
  81. channelID = extHeader(3,1:channelCount);
  82. % Reading the number of packets
  83. fseek(FID, 28, 'bof');
  84. % Calculating the number of bytes in each segment
  85. channelBytes = (dataLength)/channelCount;
  86. % Reading the headers and the data header
  87. fseek(FID, 0, 'bof');
  88. fileHeader = fread(FID, positionEOE, 'char');
  89. dataHeader = fread(FID, 9, 'char');
  90. fseek(FID, positionEOE+9, 'bof');
  91. % Reading the data
  92. fprintf('\nReading the entire data file...\n');
  93. dataSegment = fread(FID, [channelCount, channelBytes], 'int16');
  94. for idx = 1:splitCount
  95. % Determining whether tetrode channel is recorded and valid in NSx
  96. tetrodeChannels = ccf.NTrodeInfo.NTrodeMembers{idx};
  97. for tetIDX = 1:length(tetrodeChannels)
  98. validChannel = find(channelID == tetrodeChannels(tetIDX));
  99. if isempty(validChannel)
  100. fprintf(2,'The tetrode channel %1.0f from tetrode group %d does not exist in the continuous file.\n',tetrodeChannels(tetIDX), idx);
  101. break;
  102. end
  103. validChannels(tetIDX) = validChannel;
  104. end
  105. if ~isempty(validChannel)
  106. % Opening a file for saving
  107. fprintf('Writing segment %d...\n', idx);
  108. FIDw = fopen([path fname(1:end-4) '-tet' sprintf('%03d', idx) fname(end-3:end)], 'w+', 'ieee-le');
  109. % Writing the segmented data into file
  110. basicHeader(end-3) = length(validChannels);
  111. fwrite(FIDw, basicHeader, 'char');
  112. fwrite(FIDw, extHeader(:,validChannels), 'char');
  113. fwrite(FIDw, dataHeader, 'char');
  114. fwrite(FIDw, dataSegment(validChannels,:), 'int16');
  115. fclose(FIDw);
  116. end
  117. end
  118. fprintf('\n');
  119. else
  120. % Display error if non-compatible file is trying to open.
  121. disp('This version of splitNSx can only split File Specs 2.2 and 2.3');
  122. disp(['The selected file spec is ' NSx.MetaTags.FileSpec '.']);
  123. fclose(FID);
  124. clear variables;
  125. return;
  126. end