PoseExtractionSingle.m 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. function PoseExtractionSingle(pathdir, Mouse)
  2. import tools.GetCSVs;
  3. import tools.LoadCSVsAsMatrix;
  4. set(0, 'DefaultFigureVisible', 'off');
  5. % Import data from CSV file. Copy full path and file name
  6. meanDistancesPathdir = [pathdir '/Mean Distances/'];
  7. pathdir = [pathdir '/' Mouse];
  8. [labels, csvs] = GetCSVs(pathdir, Mouse);
  9. matrix = LoadCSVsAsMatrix(pathdir, csvs);
  10. mkdir meanDistancesPathdir;
  11. [nSubjs, frames, cols] = size(matrix);
  12. % Take all subjects and concat them in our matrix.
  13. % The reason this looks ugly is that:
  14. % - cat cannot concatenate a *single* matrix along an axis
  15. % - reshape does not work as it will first pick the ith row of each subject
  16. % before going to the next row, rather than iterating by subject first,
  17. % and rows seconds.
  18. % The latter is due to the fact matlab is column-major rather than row-major,
  19. % thus values are spilled by the first dimension (subjects) rather than
  20. % the one-but-last (frames);
  21. % This wouldn't be a problem hadn't it been that COLUMN MAJOR MAKES NO
  22. % FREAKING SENSE WITH TENSORS!!!
  23. ThisMouse = zeros(nSubjs*frames, cols);
  24. for i=0:nSubjs-1
  25. ThisMouse(frames*i+1:frames*(i+1), :) = matrix(i+1, :, :);
  26. end
  27. % Replace the gaps (NaN cells) with closest value in the column
  28. ThisMouseY = fillmissing(ThisMouse(:, 3:3:end), 'previous');
  29. FramesThisMouse = repmat((1:frames)', nSubjs, 1);
  30. % Makes each id start from 1 for our convenience
  31. ThisMouse(:, 1) = ThisMouse(:, 1) + 1;
  32. % Calculate Body-parts distances for the Y coordinates
  33. % by enumerating all body-part pairs
  34. DistMatrix = [];
  35. [yframes, bodyparts] = size(ThisMouseY);
  36. for i=(1:bodyparts)
  37. for j=(i+1:bodyparts)
  38. DistMatrix(end+1, :) = ThisMouseY(:, i) - ThisMouseY(:, j);
  39. end
  40. end
  41. DistMatrix = DistMatrix.';
  42. % TIME FOR CLUSTERING
  43. % FIXME the number of clusters should/could be fixed
  44. Elbow=kmeans_opt(DistMatrix); %K-mean clustering using Elbow method to determine optilan number (UNSUPERVISED)
  45. Clusters=unique(Elbow);
  46. for i=1:length(Clusters)
  47. counts(i)=sum(Elbow==Clusters(i));
  48. end
  49. clear i
  50. %POSTURE DETERMINATION
  51. %Now that the clustering is done, assign each original observation to a
  52. %cluster
  53. ClusterSummary=[Clusters, counts']; %Recall number of Frames per Cluster
  54. ClusteredDist=[FramesThisMouse,DistMatrix,Elbow]; %Distance matrix with Frames and Clusters
  55. ClusteredYData=[FramesThisMouse,ThisMouseY,Elbow]; %Original Coordinates with Clusters assigned
  56. ThisMouseClustered=[ThisMouse,Elbow]; %Original DLC output with Clusters assigned
  57. for subjId=0:nSubjs-1
  58. label = labels{subjId+1};
  59. clustered = ClusteredYData(frames*subjId+1:frames*(subjId+1), :);
  60. title = [label ' poses overtime'];
  61. fig = figure ('Name', title);
  62. scatter(clustered(:, 1), clustered(:, 8));
  63. saveas(fig, [pathdir '/' label '_over_time.png']);
  64. end
  65. % clear counts FramesThisMouse i SHAMy T1y T2y T3y DistMatrix FindSHAM FindT1 FindT2 FindT3
  66. %Starting From the ClusteredData matrix extract each single cluster and plot
  67. %the corresponding posture on a scatter plot
  68. disp(pathdir)
  69. mkdir([pathdir '/Clusters/']);
  70. for Cluster2Explore=1:length(ClusterSummary)
  71. num=length(ClusteredYData);
  72. ClusterIndex=0;
  73. for ind=1:num
  74. if ClusteredYData(ind,8)==Cluster2Explore
  75. ClusterIndex=(ClusterIndex+1);
  76. Cluster(ClusterIndex,1:8)=ClusteredYData(ind,1:8);
  77. end
  78. end
  79. NameCluster=num2str(Cluster2Explore);
  80. %assignin('base',NameCluster,Cluster);
  81. writematrix(Cluster, [pathdir '/Clusters/C' num2str(Cluster2Explore) '.csv']);
  82. ClusterMean=[mean(Cluster(:,2:7))];
  83. %Create a Representative Scatter Plot for the Cluster just analyzed
  84. fig = figure('Name',NameCluster);
  85. Ycoord=[ClusterMean/-1];
  86. Xcoord=[1:6];
  87. plot(Xcoord,Ycoord,'-x');
  88. saveas(fig, [pathdir '/Clusters/C' label '_rep.png']);
  89. ClusterIndex=(ClusterIndex+1);
  90. saveas(gcf, [pathdir '/Clusters/' num2str(ind) '-' num2str(Cluster2Explore) '.png']);
  91. AllClustersMean(Cluster2Explore,:)=mean(Cluster(:,2:end));
  92. clear Cluster
  93. end
  94. %Average the ClusteredDist Matrix for future analysis
  95. for DistIndex=1:length(ClusterSummary)
  96. [Dist2Avg]=find(ClusteredDist(:,17)==DistIndex);
  97. toAVG=[ClusteredDist(Dist2Avg,2:16)];
  98. ClusteredDistMeans(DistIndex,:)=[mean(toAVG),DistIndex];
  99. end
  100. %Create a string vetor with the Animal Code to include with the Cluster
  101. %Mean Summary
  102. code=strings(length(ClusterSummary), 1);
  103. code(:)=Mouse;
  104. %Generate Cluster Mean Summary for both Ycoordinates and Distances
  105. AllClustersMean=[code,AllClustersMean,ClusterSummary(:,2:end)];
  106. ClusteredDistMeans=[code,ClusteredDistMeans];
  107. AllClustersMean(1:end,1:1)=Mouse; %Assign the Mouse Identity to the first column of the matrix
  108. ClusteredDistMeans(1:end,1:1)=Mouse;
  109. ClusterDir = [pathdir '/Clusters/'];
  110. SummaryDir = [pathdir '/Summary/'];
  111. mkdir(ClusterDir);
  112. mkdir(SummaryDir);
  113. %Print Outcome and cluster in CSV files
  114. writematrix(AllClustersMean, [SummaryDir 'Mouse' Mouse 'CoordMeans.csv']);
  115. writematrix(ClusteredDistMeans, [meanDistancesPathdir 'Mouse' Mouse 'DistMeans.csv']);
  116. writematrix(ClusteredYData, [SummaryDir 'Clustered' Mouse 'Data.csv']);
  117. writematrix(ClusteredDist, [SummaryDir 'Clustered' Mouse 'Dist.csv']);
  118. writematrix(ThisMouseClustered, [SummaryDir 'Mouse' Mouse 'Clustered.csv']);
  119. for subjId=0:nSubjs-1
  120. label = labels{subjId+1};
  121. clustered = [ClusteredYData(frames*subjId+1:frames*(subjId+1), :)];
  122. writematrix(clustered, [ClusterDir 'Clustered' label '.csv']);
  123. end
  124. set(0, 'DefaultFigureVisible', 'on');
  125. end
  126. function [labels, fileList]=GetCSVs(pathdir, mouse)
  127. % Detect all CSVs in our file
  128. files = dir(pathdir);
  129. nfiles = size(files);
  130. fileList = {};
  131. labels = {};
  132. for i = 1:nfiles
  133. filename = files(i).name;
  134. if endsWith(filename, ".csv")
  135. suffixToStrip = '_DLC_3D.csv'; % FIXME
  136. stripped = filename(length(mouse)+2:end-length(suffixToStrip));
  137. labels{end+1} = stripped;
  138. fileList{end+1} = filename;
  139. end
  140. end
  141. end