def initialize_params(files, startingFrameNum): global lowerThreshold global pathOfCurrentParamDF global segmentVerificationDir global movementSegment global currentSegmentStartingFrame global currentSegmentEndingFrame global isChunkAnalysisFinished currentSegmentStartingFrame = startingFrameNum currentSegmentEndingFrame = startingFrameNum reinitializeElapsedTime() saveSegmentVariableParams() if startingFrameNum != 0: movementSegment += 1 if startingFrameNum + numFramesForParamInitialization < framesInChunk: fileSubset = files[startingFrameNum:startingFrameNum + numFramesForParamInitialization] else: fileSubset = files[startingFrameNum:] # create segment directory named with global movement segment segmentName = '{}_{}_{:03}'.format(recordingName, chunkName, movementSegment) segmentVerificationDir = dm.makeOutDir(segmentDir, segmentName) pathOfCurrentParamDF = segmentVerificationDir / '{}_params.csv'.format( segmentName) saveSegmentVariableParams() thresholdingDir = dm.makeOutDir(segmentVerificationDir, '{}_ThresholdingPlots'.format(segmentName)) plotDir = dm.makeOutDir(segmentVerificationDir, '{}_AngleVerificationPlots'.format(segmentName)) centroidDir = dm.makeOutDir( segmentVerificationDir, '{}_CentroidVerificationPlots'.format(segmentName)) segmentOrientationDir = dm.makeOutDir( segmentVerificationDir, '{}_RelaxedFramesForOrientation'.format(segmentName)) dynamicRangeDir = dm.makeOutDir( segmentVerificationDir, '{}_dynamicRangeNormalizationImages'.format(segmentName)) if DEBUG: print('loading initialization stack\n') init_movie = init.get_init_movie(fileSubset) if DEBUG: print('calculating lowerThreshold\n') lowerThreshold = init.autoLowerThreshold( init_movie, roughness_saveOut_dir=thresholdingDir) saveSegmentVariableParams() # get areas of jellies both the region and the whole value true in binary image. binaryImageAreas = init.getBinaryAreas(init_movie, lowerThreshold) peaksOnBinaryImage = init.downturnFinder( init_movie, postPeakRefractoryPeriod, lowerThreshold, numConsecutiveDrops, peak2InflectionDiff, peak2TroughDiff) plotOutpath = segmentVerificationDir / '{}_areaPlot.png'.format( segmentName) init.saveAreasPlot(binaryImageAreas, peaksOnBinaryImage, plotOutpath, [ peak2InflectionDiff, peak2InflectionDiff + inflectionTestDiff, peak2TroughDiff ], postPeakRefractoryPeriod) saveSegmentVariableParams() i = 0 while i < len(peaksOnBinaryImage): if peaksOnBinaryImage[ i] + peak2InflectionDiff < 0 or peaksOnBinaryImage[ i] + peak2TroughDiff >= numFramesForParamInitialization: peaksOnBinaryImage.pop(i) else: i += 1 for i, peak in enumerate(peaksOnBinaryImage): relaxedInfile = fileSubset[peak + peak2InflectionDiff] testInfile = fileSubset[peak + peak2InflectionDiff + inflectionTestDiff] peakInfile = fileSubset[peak] troughInfile = fileSubset[peak + peak2TroughDiff] relaxedImg = im.getJellyGrayImageFromFile(relaxedInfile) testImg = im.getJellyGrayImageFromFile(testInfile) peakImg = im.getJellyGrayImageFromFile(peakInfile) troughImg = im.getJellyGrayImageFromFile(troughInfile) centroidDiff = im.getGrayscaleImageDiff_absolute(troughImg, relaxedImg) binaryCentroidDiff = im.getBinaryJelly(centroidDiff, lower_bound=0.05) centroidRegion = im.findJellyRegion(binaryCentroidDiff) centroid = im.findCentroid_boundingBox(centroidRegion) centroidVerOutFile = centroidDir / 'centroid for {}_{:03}.png'.format( segmentName, peak + peak2InflectionDiff) im.saveJellyPlot( im.getCentroidVerificationImg(centroidDiff, binaryCentroidDiff, centroid), centroidVerOutFile) if i == 0: orientationFrameStamp = dm.getFrameNumFromFile(peakInfile) orientationTimeStamp = int(orientationFrameStamp / framerate) orientationOutFile = orientationDir / '{}_ts_{:02}h_{:02}m_{:02}s_{:03}.png'.format( chunkName, int(orientationTimeStamp / 3600), int(orientationTimeStamp / 60) % 60, orientationTimeStamp % 60, movementSegment) im.saveJellyPlot(relaxedImg, orientationOutFile, [centroid, (centroid[0], 15)]) orientationOutFile = segmentOrientationDir / 'relaxedFrame_{:03}.png'.format( peak + peak2InflectionDiff) im.saveJellyPlot(relaxedImg, orientationOutFile, [centroid, (centroid[0], 15)]) peakDiff = im.getGrayscaleImageDiff_absolute(troughImg, peakImg) binaryPeakDiff = im.getBinaryJelly(peakDiff, lower_bound=0.05, upper_bound=1) averagedDynamicRangeMaskedImg = im.dynamicRangeImg_AreaBased( relaxedImg, binaryPeakDiff, 5) dynamicRangeImgOutfile = dynamicRangeDir / 'dynamicRangeImg_{:03}.png'.format( peak + peak2InflectionDiff) im.saveJellyPlot(averagedDynamicRangeMaskedImg, dynamicRangeImgOutfile) testDiff = im.getGrayscaleImageDiff_absolute(testImg, relaxedImg) normalizedTestDiff = testDiff / averagedDynamicRangeMaskedImg binaryDiffImg = im.getBinaryJelly( normalizedTestDiff, lower_bound=inflectionTestBinaryThreshold) biggestRegion = im.findJellyRegion(binaryDiffImg) if biggestRegion is not None: local_com = im.findCentroid_regionProp(biggestRegion) zeroDegreePoint = (centroid[0], 0) testingOutfile = plotDir / 'testPlot for {} - {:03}.png'.format( segmentName, peak + peak2InflectionDiff) im.saveJellyPlot(binaryDiffImg, testingOutfile, [centroid, zeroDegreePoint, local_com]) else: testingOutfile = plotDir / 'testPlot for {} - {:03}.png'.format( segmentName, peak + peak2InflectionDiff) im.saveJellyPlot(binaryDiffImg, testingOutfile, [centroid]) # saves important parameters used in analysis to csv saveSegmentVariableParams() if DEBUG: print('saved parameter data') if DEBUG: print('finished saving outplots and angle verification at: {}'.format( segmentVerificationDir)) return True
def differenceAngleFinder(files): global currentSegmentEndingFrame i = 0 # movement parameters firstStationaryAfterMovement = 0 # first stationary frame (i) after movement isMoving = False isQuestionablyStationary = False centroidBefore = None lastStationaryCentroid = None counter = 0 peak = 0 pulseCountInQuestionablyStationary = 0 centroid = None data = [] movingPeaks = [] # initializes lists with 'numConsecutiveDrops' of files def reinitializeTestFramesAndAreas(j): testFrames = [ ] # this list should never be more than 5 entries long, ex. [51, 52, 53, 54, 55] testAreas = [ ] # this list should never be more than 5 entries long, ex. [253, 255, 256, 255, 255] while len(testFrames) < numConsecutiveDrops and j < framesInChunk: image = im.getJellyImageFromFile(files[j]) binary_image = im.getBinaryJelly(image, lowerThreshold) area = im.findBinaryArea(binary_image) testFrames.append(j) testAreas.append(area) j += 1 return testFrames, testAreas, j # function to save out data def saveOutData(): df = pd.DataFrame(data, columns=[ 'global frame', 'chunk frame', 'angle', 'centroid x', 'centroid y' ]) if DEBUG: print(df.head()) dataTitle = '{}_{:03}.csv'.format(chunkName, movementSegment) df.to_csv(str(angleOutputDir / dataTitle), index=False) testFrames, testAreas, i = reinitializeTestFramesAndAreas(i) try: while i < framesInChunk: isDownturn = dm.is_downturn(0, testAreas, numConsecutiveDrops) if isDownturn: peak = i - numConsecutiveDrops print("chunk: {}, i: {}, peak: {}".format(chunkName, i, peak)) # checks that peaks are within testing bounds if peak + peak2InflectionDiff >= 0 and peak + peak2TroughDiff < framesInChunk: troughInfile = files[peak + peak2TroughDiff] relaxedInfile = files[peak + peak2InflectionDiff] troughImg = im.getJellyGrayImageFromFile(troughInfile) relaxedImg = im.getJellyGrayImageFromFile(relaxedInfile) centroidDiff = im.getGrayscaleImageDiff_absolute( troughImg, relaxedImg) binaryCentroidDiff = im.getBinaryJelly(centroidDiff, lower_bound=0.05, upper_bound=1) centroidRegion = im.findJellyRegion(binaryCentroidDiff) centroid = im.findCentroid_boundingBox(centroidRegion) if lastStationaryCentroid is None: lastStationaryCentroid = centroid if CONFIRMATIONIMAGES: im.saveJellyPlot( im.getCentroidVerificationImg( centroidDiff, binaryCentroidDiff, centroid), str(confirmationImagesPath / '{}_{}_centroid.png'.format(peak, chunkName))) if isMoving: data.append([ peak + lastFrameOfPreviousChunk, peak, np.nan, centroid[0], centroid[1] ]) movedBefore = isMoving isMoving = im.distance(centroid, lastStationaryCentroid ) > movementThreshold2KeepMoving lastStationaryCentroid = centroid if movedBefore and not isMoving: firstStationaryAfterMovement = i pulseCountInQuestionablyStationary = 0 isQuestionablyStationary = True elif isQuestionablyStationary: data.append([ peak + lastFrameOfPreviousChunk, peak, np.nan, centroid[0], centroid[1] ]) isMoving = im.distance( centroid, lastStationaryCentroid ) > movementThreshold4reinitialization if isMoving: movingPeaks.append(peak) isQuestionablyStationary = False pulseCountInQuestionablyStationary += 1 if i - firstStationaryAfterMovement > numFrames2ConfirmStationary: # now there is confirmed time after initial stationary point if firstStationaryAfterMovement == 0: data = [] else: # must mutate data to take out data = data[: -pulseCountInQuestionablyStationary] currentSegmentEndingFrame = i saveSegmentVariableParams() saveOutData() data = [] i = firstStationaryAfterMovement # peak2InflectionDiff, peak2TroughDiff, postPeakRefractoryPeriod, infflectionTestDiff, # inflectionTestBinaryThreshold, and chosen SD are all static. initialize_params(files, i) isQuestionablyStationary = False pulseCountInQuestionablyStationary = 0 # until count from current i to last stationary i reaches this point, # the program is in a holding pattern of sorts. else: testInfile = files[peak + peak2InflectionDiff + inflectionTestDiff] testImg = im.getJellyGrayImageFromFile(testInfile) if CONFIRMATIONIMAGES: plt.imsave( str(confirmationImagesPath / '{}_{}_interestFrames.png'.format( peak, chunkName)), im.juxtaposeImages( np.array([[ relaxedImg, testImg, peakImg, troughImg ]]))) if centroidBefore is not None: reinitializeAreaPlot = im.distance( centroid, centroidBefore ) > movementThreshold4newNormalizationImg if reinitializeAreaPlot: peakInfile = files[peak] peakImg = im.getJellyGrayImageFromFile( peakInfile) peakDiff = im.getGrayscaleImageDiff_absolute( troughImg, peakImg) binaryPeakDiff = im.getBinaryJelly( peakDiff, lower_bound=0.05, upper_bound=1) averagedDynamicRangeMaskedImg = im.dynamicRangeImg_AreaBased( relaxedImg, binaryPeakDiff, 5) else: peakInfile = files[peak] peakImg = im.getJellyGrayImageFromFile(peakInfile) peakDiff = im.getGrayscaleImageDiff_absolute( troughImg, peakImg) binaryPeakDiff = im.getBinaryJelly( peakDiff, lower_bound=0.05, upper_bound=1) averagedDynamicRangeMaskedImg = im.dynamicRangeImg_AreaBased( relaxedImg, binaryPeakDiff, 5) centroidBefore = centroid if CONFIRMATIONIMAGES: im.saveJellyPlot( averagedDynamicRangeMaskedImg, str(confirmationImagesPath / '{}_{}_dynRng.png'.format(peak, chunkName))) testDiff = im.getGrayscaleImageDiff_absolute( testImg, relaxedImg) normalizedTestDiff = testDiff / averagedDynamicRangeMaskedImg binaryDiffImg = im.getBinaryJelly( normalizedTestDiff, lower_bound=inflectionTestBinaryThreshold) biggestRegion = im.findJellyRegion(binaryDiffImg) if biggestRegion is not None: local_com = im.findCentroid_regionProp( biggestRegion) zeroDegreePoint = (centroid[0], 0) angle = dm.getAngle(zeroDegreePoint, centroid, local_com) if CONFIRMATIONIMAGES: im.saveJellyPlot( binaryDiffImg, str(confirmationImagesPath / '{}_{}_angle.png'.format( peak, chunkName)), [centroid, local_com, zeroDegreePoint]) else: angle = np.nan if CONFIRMATIONIMAGES: im.saveJellyPlot( binaryDiffImg, str(confirmationImagesPath / '{}_{}_angle.png'.format( peak, chunkName)), [centroid]) data.append([ peak + lastFrameOfPreviousChunk, peak, angle, centroid[0], centroid[1] ]) movedBefore = isMoving isMoving = im.distance( centroid, lastStationaryCentroid ) > movementThreshold4reinitialization if isMoving and not movedBefore: isQuestionablyStationary = False lastStationaryCentroid = centroid i += postPeakRefractoryPeriod counter += 1 testFrames, testAreas, i = reinitializeTestFramesAndAreas(i) else: testFrames.pop(0) testAreas.pop(0) image = im.getJellyImageFromFile(files[i]) binary_image = im.getBinaryJelly(image, lowerThreshold) area = im.findBinaryArea(binary_image) testFrames.append(i) testAreas.append(area) i += 1 counter += 1 except Exception as error: print('{} error occured.'.format(error)) print( "chunkName: {}, index: {}, isMoving: {}, isQStat: {}, centroid: {}" .format(chunkName, i, isMoving, isQuestionablyStationary, str(centroid))) raise finally: currentSegmentEndingFrame = i saveSegmentVariableParams() saveOutData()
def selectInflectionThresholdandDiff(peaksOnBinaryImage, init_movie, recordingName, peak2InflectionDiff, peak2TroughDiff, use_conserved_trough, initializationOutputDir, angleArrImageDir, centroidDir, dynamicRangeDir): if use_conserved_trough: peaksOnBinaryImage = [x - peak2TroughDiff for x in peaksOnBinaryImage] # make directory to store verification jelly plots postInflectionDiffCases = list(range(2, 12)) thresholdCases = [0.1, 0.15, 0.2, 0.25, 0.3, 0.4, 0.5] # out data: pulse angles x testDiffs angleData = np.empty( (len(peaksOnBinaryImage), len(postInflectionDiffCases), len(thresholdCases))) # 3D array angleData[:] = np.nan otherDataCols = np.array(['relaxed', 'peak', 'trough', 'by eye', '']) otherData = np.empty((len(peaksOnBinaryImage), len(otherDataCols))) otherData[:] = np.nan # read in by eye angle measurements byEyeAngleDF = pd.DataFrame(peaksOnBinaryImage, columns=['peaks']) byEyeAngleDF['by eye measurement (0 to 360)'] = np.nan byEyeAngleDFioPath = initializationOutputDir / '{}_byEyeAngles.csv'.format( recordingName) byEyeAngleDF.to_csv(str(byEyeAngleDFioPath), index=False) for i, peak in enumerate(peaksOnBinaryImage): if DEBUG: print("{}: {}".format(i, peak)) troughImg = init_movie[peak + peak2TroughDiff] relaxedImg = init_movie[peak + peak2InflectionDiff] centroidDiff = im.getGrayscaleImageDiff_absolute(troughImg, relaxedImg) binaryCentroidDiff = im.getBinaryJelly(centroidDiff, lower_bound=0.05) centroidRegion = im.findJellyRegion(binaryCentroidDiff)[0] centroid = im.findCentroid_boundingBox(centroidRegion) centroidVerOutFile = centroidDir / 'centroid for {} - {:03}.png'.format( recordingName, peak + peak2InflectionDiff) im.saveJellyPlot( im.getCentroidVerificationImg(centroidDiff, binaryCentroidDiff, centroid), centroidVerOutFile) peakImg = init_movie[peak] peakDiff = im.getGrayscaleImageDiff_absolute(troughImg, peakImg) binaryPeakDiff = im.getBinaryJelly(peakDiff, lower_bound=0.05) if np.sum(binaryCentroidDiff) > np.sum(binaryPeakDiff): binaryPeakDiff = binaryCentroidDiff averagedDynamicRangeMaskedImg = im.dynamicRangeImg_AreaBased( relaxedImg, binaryPeakDiff, 5) dynamicRangeImgOutfile = dynamicRangeDir / 'dynamicRangeImg_{:03}.png'.format( peak + peak2InflectionDiff) im.saveJellyPlot(averagedDynamicRangeMaskedImg, dynamicRangeImgOutfile) # dealing with inflection thresholding testDiffImages = [] for j in postInflectionDiffCases: testImg = init_movie[peak + peak2InflectionDiff + j] testDiff = im.getGrayscaleImageDiff_absolute(testImg, relaxedImg) normalizedTestDiff = testDiff / averagedDynamicRangeMaskedImg testDiffImages.append(normalizedTestDiff) testingOutfile = angleArrImageDir / 'testPlot for {} - {:03}.png'.format( recordingName, peak + peak2InflectionDiff) pulseAngleData = im.saveDifferenceTestingAggregationImage( relaxedImg, testDiffImages, thresholdCases, testingOutfile, discludeVerificationArrayImg=False, centroid=centroid) for n, row in enumerate(pulseAngleData): for m, angle in enumerate(row): angleData[i][m][n] = angle otherData[i][0] = peak + peak2InflectionDiff otherData[i][1] = peak otherData[i][2] = peak + peak2TroughDiff angleDataAsRows = [x.ravel() for x in angleData] pulseAngleOutput = np.concatenate( (np.tile([postInflectionDiffCases], len(thresholdCases)), angleDataAsRows)) otherDataOut = np.concatenate(([otherDataCols], otherData)) # warning: this results in mixed data. This cannot be saved by numpy csv methods. Pandas is easiest way to save. outframe = np.concatenate((otherDataOut, pulseAngleOutput), axis=1) # saves data into verification frame dfOut = pd.DataFrame(outframe) dataTitle = '{}_testDifferenceVerification.csv'.format(recordingName) verificationCSVOutFile = initializationOutputDir / dataTitle dfOut.to_csv(str(verificationCSVOutFile), header=False, index=False) # setting test difference and threshold def runSDanalysis(): if CHIME: dm.chime(MAC, 'input time') print('time to enter by eye angles for each pulse') print('entries must be from 0 to 360') print('Enter \'1\' to continue.') dm.getSelection([1]) byEyeAngleDF = pd.read_csv(str(byEyeAngleDFioPath)) byEyeAngles = byEyeAngleDF['by eye measurement (0 to 360)'].tolist() i = 0 while i < len(byEyeAngles): if byEyeAngles[i] == np.nan: np.delete(angleData, i, 0) byEyeAngles.pop(i) else: i += 1 angleDataShape = angleData.shape diff2byeye = np.empty( (angleDataShape[2], angleDataShape[1], angleDataShape[0])) diff2byeye[:] = np.nan for i in range(angleDataShape[0]): for j in range(angleDataShape[1]): for k in range(angleDataShape[2]): diff2byeye[k][j][i] = dm.angleDifferenceCalc( angleData[i][j][k], byEyeAngles[i]) squaredDiffs = np.square(diff2byeye) summedDiffs = np.sum(squaredDiffs, axis=2) varianceTable = summedDiffs / diff2byeye.shape[2] sdTable = np.sqrt(varianceTable) sdTableMinIndex = list([ np.where(sdTable == np.nanmin(sdTable))[0][0], np.where(sdTable == np.nanmin(sdTable))[1][0] ]) lowSDthresholds = [] lowSDtestFrames = [] for x in np.sort(sdTable.ravel())[0:5]: loc = np.where(sdTable == x) lowSDthresholds.append(loc[0][0]) lowSDtestFrames.append(loc[1][0]) inflectionTestBinaryThreshold = thresholdCases[int( np.median(lowSDthresholds))] inflectionTestDiff = postInflectionDiffCases[int( np.median(lowSDtestFrames))] return inflectionTestBinaryThreshold, inflectionTestDiff, sdTable, sdTableMinIndex inflectionTestBinaryThreshold, inflectionTestDiff, sdTable, sdTableMinIndex = runSDanalysis( ) if CHIME: dm.chime(MAC, 'input time') while True: print('thresholding options: {}'.format(thresholdCases)) print('test frame options: {}'.format(postInflectionDiffCases)) np.set_printoptions(threshold=np.inf) print(np.asarray(sdTable)) print('index of min sd: {}'.format(sdTableMinIndex)) print('selected sd: {}'.format( sdTable[thresholdCases.index(inflectionTestBinaryThreshold)][ postInflectionDiffCases.index(inflectionTestDiff)])) print('Params to change: ') print('select \'1\' to change {} which is {}'.format( 'inflectionTestBinaryThreshold', inflectionTestBinaryThreshold)) print('select \'2\' to change {} which is {}'.format( 'inflectionTestDiff', inflectionTestDiff)) print('select \'3\' to update by eye measurements') print('or \'4\' to continue.') selectionVar = dm.getSelection([1, 2, 3, 4]) if selectionVar == '1': inflectionTestBinaryThreshold = float( dm.getSelection(thresholdCases)) elif selectionVar == '2': inflectionTestDiff = int(dm.getSelection(postInflectionDiffCases)) elif selectionVar == '3': inflectionTestBinaryThreshold, inflectionTestDiff, sdTable, sdTableMinIndex = runSDanalysis( ) else: break chosenSD = sdTable[thresholdCases.index(inflectionTestBinaryThreshold)][ postInflectionDiffCases.index(inflectionTestDiff)] return inflectionTestDiff, inflectionTestBinaryThreshold, chosenSD