pairwiseDistanceStatsVsAnisotropicScaling.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. import json
  2. import numpy as np
  3. import pandas as pd
  4. from statsmodels.sandbox.descstats import sign_test
  5. import os
  6. def pairwiseDistanceStats(parFile, anisotropicScalingThresh):
  7. with open(parFile) as fle:
  8. parsList = json.load(fle)
  9. transErrs = pd.DataFrame()
  10. signStats = pd.DataFrame()
  11. allSizes = []
  12. allThreshs = []
  13. for parInd, par in enumerate(parsList):
  14. refSWC = par['refSWC']
  15. resFile = par['resFile']
  16. testSWC = par['testSWC']
  17. testName = resFile[:-4]
  18. thresh = par['gridSizes'][-1]
  19. print('Doing ' + repr((refSWC, resFile)))
  20. refPts = np.loadtxt(refSWC)[:, 2:5]
  21. testPtsFull = np.loadtxt(resFile)
  22. testPts = testPtsFull[:, 2:5]
  23. if refPts.shape[0] != testPts.shape[0]:
  24. print('Number of points do not match for ' + refSWC + 'and' + resFile)
  25. continue
  26. allSizes.append(refPts.shape[0])
  27. allThreshs.append(thresh)
  28. ptDiff = np.linalg.norm(refPts - testPts, axis=1)
  29. origJSON = testSWC[:-4] + '.json'
  30. if os.path.isfile(origJSON):
  31. with open(origJSON, 'r') as fle:
  32. pars = json.load(fle)
  33. scales = np.array(pars['scale'])
  34. else:
  35. raise (IOError('File not found: {}'.format(origJSON)))
  36. scalesOrdered = np.sort(scales)
  37. scalesRelative = np.mean([scalesOrdered[0] / scalesOrdered[1],
  38. scalesOrdered[0] / scalesOrdered[2],
  39. scalesOrdered[1] / scalesOrdered[2]])
  40. tempDF = pd.DataFrame()
  41. tempDF['Pairwise Distance in $\mu$m'] = ptDiff
  42. tempDF['Exp. Name'] = testName
  43. tempDF["Node ID"] = testPtsFull[:, 0]
  44. tempDF['Anisotropic Scaling Level'] = scalesRelative
  45. transErrs = transErrs.append(tempDF, ignore_index=True)
  46. t, p = sign_test(ptDiff, thresh)
  47. oneSidedP = 0.5 * p
  48. signCloserThanSmallestVoxelSize = t < 0 and oneSidedP < 0.01
  49. notSignFartherThanSVS = not (t > 0 and oneSidedP < 0.01)
  50. tempDict = {"Job Number": parInd, "resFile": resFile, "refSWC": refSWC,
  51. "t Statistic": t, "One Sided p value": oneSidedP,
  52. "Pairwise distance significantly smaller than smallest voxel size":
  53. signCloserThanSmallestVoxelSize,
  54. "Pairwise distance not significantly larger than smallest voxel size":
  55. notSignFartherThanSVS,
  56. "Anisotropic Scaling Level": scalesRelative
  57. }
  58. signStats = signStats.append(tempDict, ignore_index=True)
  59. allEqualSizeThresh = (allSizes.count(allSizes[0]) == len(allSizes)) and \
  60. (allThreshs.count(allThreshs[0]) == len(allThreshs))
  61. nodeWiseStatsDF = pd.DataFrame()
  62. if allEqualSizeThresh:
  63. transErrsAnisoThresh = transErrs.loc[transErrs['Anisotropic Scaling Level'] >= anisotropicScalingThresh, :]
  64. transErrsGBNodeID = transErrs.groupby("Node ID")
  65. transErrsGBNodeIDAnisoThresh = transErrsAnisoThresh.groupby("Node ID")
  66. for nodeInd, (node, nodeDistsDF) in enumerate(transErrsGBNodeID):
  67. print("Doing node {}, {} of {}".format(node, nodeInd, len(transErrsGBNodeID.indices)))
  68. nodeDistsAll = nodeDistsDF['Pairwise Distance in $\mu$m'].astype(float)
  69. t, p = sign_test(nodeDistsAll, allThreshs[0])
  70. oneSidedP = 0.5 * p
  71. signCloserThanSmallestVoxelSize = t < 0 and oneSidedP < 0.05
  72. notSignFartherThanSVS = not (t > 0 and oneSidedP < 0.01)
  73. tempDict = {
  74. "[All] Pairwise distance significantly smaller than smallest voxel size": signCloserThanSmallestVoxelSize,
  75. "[All] Pairwise distance not significantly larger than smallest voxel size": notSignFartherThanSVS
  76. }
  77. nodeDistsDFAnisoFiltered = transErrsGBNodeIDAnisoThresh.get_group(node)
  78. nodeDistsAnisoFiltered = nodeDistsDFAnisoFiltered['Pairwise Distance in $\mu$m'].astype(float)
  79. t, p = sign_test(nodeDistsAnisoFiltered,
  80. allThreshs[0])
  81. oneSidedP = 0.5 * p
  82. signCloserThanSmallestVoxelSize = t < 0 and oneSidedP < 0.01
  83. notSignFartherThanSVS = not (t > 0 and oneSidedP < 0.01)
  84. tempDict["[AnisoFiltered] Pairwise distance significantly smaller than smallest voxel size"] =\
  85. signCloserThanSmallestVoxelSize
  86. tempDict["[AnisoFiltered] Pairwise distance not significantly larger than smallest voxel size"]=\
  87. notSignFartherThanSVS
  88. nodeWiseStatsDF = nodeWiseStatsDF.append(tempDict, ignore_index=True)
  89. nodesCloserThanCount = nodeWiseStatsDF["[All] Pairwise distance significantly smaller than smallest voxel size"].sum()
  90. nodesNotFartherThanCount = nodeWiseStatsDF["[All] Pairwise distance not significantly larger than smallest voxel size"].sum()
  91. nodesCloserThanCountAniso = nodeWiseStatsDF["[AnisoFiltered] Pairwise distance significantly smaller than smallest voxel size"].sum()
  92. nodesNotFartherThanCountAniso = nodeWiseStatsDF["[AnisoFiltered] Pairwise distance not significantly larger than smallest voxel size"].sum()
  93. print("[All] Nodes with pairwise distance "
  94. "significantly smaller "
  95. "than lowest voxel size: {} out of {}, {}%".format(nodesCloserThanCount,
  96. nodeWiseStatsDF.shape[0],
  97. 100 * nodesCloserThanCount / nodeWiseStatsDF.shape[0]))
  98. print("[All] Nodes with pairwise distance "
  99. "not significantly larger "
  100. "than lowest voxel size: {} out of {}, {}%".format(nodesNotFartherThanCount,
  101. nodeWiseStatsDF.shape[0],
  102. 100 * nodesNotFartherThanCount / nodeWiseStatsDF.shape[0]))
  103. print("[Aniso] Nodes with pairwise distance "
  104. "significantly smaller "
  105. "than lowest voxel size: {} out of {}, {}%".format(nodesCloserThanCountAniso,
  106. nodeWiseStatsDF.shape[0],
  107. 100 * nodesCloserThanCountAniso / nodeWiseStatsDF.shape[0]))
  108. print("[Aniso] Nodes with pairwise distance "
  109. "not significantly larger "
  110. "than lowest voxel size: {} out of {}, {}%".format(nodesNotFartherThanCountAniso,
  111. nodeWiseStatsDF.shape[0],
  112. 100 * nodesNotFartherThanCountAniso / nodeWiseStatsDF.shape[0]))
  113. signStatsAniso = signStats.loc[signStats["Anisotropic Scaling Level"] > anisotropicScalingThresh, :]
  114. signCloserThanAniso = signStatsAniso["Pairwise distance significantly smaller than smallest voxel size"]
  115. signCloserThanCountAniso = signCloserThanAniso.sum()
  116. notSignFartherAniso = signStatsAniso["Pairwise distance not significantly larger than smallest voxel size"]
  117. notSignFartherCountAniso = notSignFartherAniso.sum()
  118. print("[Aniso Filtered] Jobs with "
  119. "pairwise distance "
  120. "significantly smaller "
  121. "than lowest voxel size: {} out of {}, {}%".format(signCloserThanCountAniso,
  122. signStatsAniso.shape[0],
  123. 100 * signCloserThanCountAniso / signStatsAniso.shape[0]))
  124. print("[Aniso Filtered] Jobs with "
  125. "pairwise distance "
  126. "not significantly larger "
  127. "than lowest voxel size: {} out of {}, {}%".format(notSignFartherCountAniso,
  128. signStatsAniso.shape[0],
  129. 100 * notSignFartherCountAniso / signStatsAniso.shape[0]))
  130. signCloserThan = signStats["Pairwise distance significantly smaller than smallest voxel size"]
  131. signCloserThanCount = signCloserThan.sum()
  132. notSignFarther = signStats["Pairwise distance not significantly larger than smallest voxel size"]
  133. notSignFartherCount = notSignFarther.sum()
  134. print("[All] Jobs with "
  135. "pairwise distance "
  136. "significantly smaller "
  137. "than lowest voxel size: {} out of {}, {}%".format(signCloserThanCount, len(parsList),
  138. 100 * signCloserThanCount / len(parsList)))
  139. print("[All] Jobs with "
  140. "pairwise distance "
  141. "not significantly larger "
  142. "than lowest voxel size: {} out of {}, {}%".format(notSignFartherCount, len(parsList),
  143. 100 * notSignFartherCount / len(parsList)))
  144. # ----------------------------------------------------------------------------------------------------------------------
  145. if __name__ == '__main__':
  146. import sys
  147. assert len(sys.argv) == 3, 'Improper usage! Please use as \n' \
  148. '\'python plotPairwiseDistance.py parFile <anisotropic scaling Thresholdx>\''
  149. parFile = sys.argv[1]
  150. figs = pairwiseDistanceStats(parFile, float(sys.argv[2]))