def execute(self, slot, subindex, roi, result): t1 = time.time() key = roi.toSlice() nlabels=self.inputs["LabelsCount"].value traceLogger.debug("OpPredictRandomForest: Requesting classifier. roi={}".format(roi)) forests=self.inputs["Classifier"][:].wait() if forests is None: # Training operator may return 'None' if there was no data to train with return numpy.zeros(numpy.subtract(roi.stop, roi.start), dtype=numpy.float32)[...] traceLogger.debug("OpPredictRandomForest: Got classifier") #assert RF.labelCount() == nlabels, "ERROR: OpPredictRandomForest, labelCount differs from true labelCount! %r vs. %r" % (RF.labelCount(), nlabels) newKey = key[:-1] newKey += (slice(0,self.inputs["Image"].meta.shape[-1],None),) res = self.inputs["Image"][newKey].wait() shape=res.shape prod = numpy.prod(shape[:-1]) res.shape = (prod, shape[-1]) features=res predictions = [0]*len(forests) def predict_forest(number): predictions[number] = forests[number].predictProbabilities(numpy.asarray(features, dtype=numpy.float32)) t2 = time.time() # predict the data with all the forests in parallel pool = Pool() for i,f in enumerate(forests): req = pool.request(partial(predict_forest, i)) pool.wait() pool.clean() prediction=numpy.dstack(predictions) prediction = numpy.average(prediction, axis=2) prediction.shape = shape[:-1] + (forests[0].labelCount(),) #prediction = prediction.reshape(*(shape[:-1] + (forests[0].labelCount(),))) # If our LabelsCount is higher than the number of labels in the training set, # then our results aren't really valid. FIXME !!! # Duplicate the last label's predictions for c in range(result.shape[-1]): result[...,c] = prediction[...,min(c+key[-1].start, prediction.shape[-1]-1)] t3 = time.time() # logger.info("Predict took %fseconds, actual RF time was %fs, feature time was %fs" % (t3-t1, t3-t2, t2-t1)) return result
def execute(self, slot, subindex, roi, result): progress = 0 self.progressSignal(progress) numImages = len(self.Images) key = roi.toSlice() featMatrix=[] labelsMatrix=[] for i,labels in enumerate(self.inputs["Labels"]): if labels.meta.shape is not None: #labels=labels[:].allocate().wait() blocks = self.inputs["nonzeroLabelBlocks"][i][0].allocate().wait() progress += 10/numImages self.progressSignal(progress) reqlistlabels = [] reqlistfeat = [] traceLogger.debug("Sending requests for {} non-zero blocks (labels and data)".format( len(blocks[0])) ) for b in blocks[0]: request = labels[b].allocate() featurekey = list(b) featurekey[-1] = slice(None, None, None) request2 = self.inputs["Images"][i][featurekey].allocate() reqlistlabels.append(request) reqlistfeat.append(request2) traceLogger.debug("Requests prepared") numLabelBlocks = len(reqlistlabels) progress_outer = [progress] # Store in list for closure access if numLabelBlocks > 0: progressInc = (80-10)/numLabelBlocks/numImages def progressNotify(req): # Note: If we wanted perfect progress reporting, we could use lock here # to protect the progress from being incremented simultaneously. # But that would slow things down and imperfect reporting is okay for our purposes. progress_outer[0] += progressInc/2 self.progressSignal(progress_outer[0]) for ir, req in enumerate(reqlistfeat): image = req.notify(progressNotify) for ir, req in enumerate(reqlistlabels): labblock = req.notify(progressNotify) traceLogger.debug("Requests fired") for ir, req in enumerate(reqlistlabels): traceLogger.debug("Waiting for a label block...") labblock = req.wait() traceLogger.debug("Waiting for an image block...") image = reqlistfeat[ir].wait() indexes=numpy.nonzero(labblock[...,0].view(numpy.ndarray)) features=image[indexes] labbla=labblock[indexes] featMatrix.append(features) labelsMatrix.append(labbla) progress = progress_outer[0] traceLogger.debug("Requests processed") self.progressSignal(80/numImages) if len(featMatrix) == 0 or len(labelsMatrix) == 0: # If there was no actual data for the random forest to train with, we return None result[:] = None else: featMatrix=numpy.concatenate(featMatrix,axis=0) labelsMatrix=numpy.concatenate(labelsMatrix,axis=0) maxLabel = self.inputs["MaxLabel"].value labelList = range(1, maxLabel+1) if maxLabel > 0 else list() try: logger.debug("Learning with Vigra...") # train and store self._forest_count forests in parallel pool = Pool() for i in range(self._forest_count): def train_and_store(number): result[number] = vigra.learning.RandomForest(self._tree_count, labels=labelList) result[number].learnRF( numpy.asarray(featMatrix, dtype=numpy.float32), numpy.asarray(labelsMatrix, dtype=numpy.uint32)) req = pool.request(partial(train_and_store, i)) pool.wait() pool.clean() logger.debug("Vigra finished") except: logger.error( "ERROR: could not learn classifier" ) logger.error( "featMatrix shape={}, max={}, dtype={}".format(featMatrix.shape, featMatrix.max(), featMatrix.dtype) ) logger.error( "labelsMatrix shape={}, max={}, dtype={}".format(labelsMatrix.shape, labelsMatrix.max(), labelsMatrix.dtype ) ) raise finally: self.progressSignal(100) return result
def execute(self, slot, subindex, rroi, result): assert slot == self.Features or slot == self.Output if slot == self.Features: key = roiToSlice(rroi.start, rroi.stop) index = subindex[0] subslot = self.Features[index] key = list(key) channelIndex = self.Input.meta.axistags.index('c') # Translate channel slice to the correct location for the output slot. key[channelIndex] = slice(self.featureOutputChannels[index][0] + key[channelIndex].start, self.featureOutputChannels[index][0] + key[channelIndex].stop) rroi = SubRegion(subslot, pslice=key) # Get output slot region for this channel return self.execute(self.Output, (), rroi, result) elif slot == self.outputs["Output"]: key = rroi.toSlice() cnt = 0 written = 0 assert (rroi.stop<=self.outputs["Output"].meta.shape).all() flag = 'c' channelAxis=self.inputs["Input"].meta.axistags.index('c') axisindex = channelAxis oldkey = list(key) oldkey.pop(axisindex) inShape = self.inputs["Input"].meta.shape shape = self.outputs["Output"].meta.shape axistags = self.inputs["Input"].meta.axistags result = result.view(vigra.VigraArray) result.axistags = copy.copy(axistags) hasTimeAxis = self.inputs["Input"].meta.axistags.axisTypeCount(vigra.AxisType.Time) timeAxis=self.inputs["Input"].meta.axistags.index('t') subkey = popFlagsFromTheKey(key,axistags,'c') subshape=popFlagsFromTheKey(shape,axistags,'c') at2 = copy.copy(axistags) at2.dropChannelAxis() subshape=popFlagsFromTheKey(subshape,at2,'t') subkey = popFlagsFromTheKey(subkey,at2,'t') oldstart, oldstop = roi.sliceToRoi(key, shape) start, stop = roi.sliceToRoi(subkey,subkey) maxSigma = max(0.7,self.maxSigma) # The region of the smoothed image we need to give to the feature filter (in terms of INPUT coordinates) vigOpSourceStart, vigOpSourceStop = roi.extendSlice(start, stop, subshape, 0.7, window = 2) # The region of the input that we need to give to the smoothing operator (in terms of INPUT coordinates) newStart, newStop = roi.extendSlice(vigOpSourceStart, vigOpSourceStop, subshape, maxSigma, window = 3.5) # Translate coordinates (now in terms of smoothed image coordinates) vigOpSourceStart = roi.TinyVector(vigOpSourceStart - newStart) vigOpSourceStop = roi.TinyVector(vigOpSourceStop - newStart) readKey = roi.roiToSlice(newStart, newStop) writeNewStart = start - newStart writeNewStop = writeNewStart + stop - start treadKey=list(readKey) if hasTimeAxis: if timeAxis < channelAxis: treadKey.insert(timeAxis, key[timeAxis]) else: treadKey.insert(timeAxis-1, key[timeAxis]) if self.inputs["Input"].meta.axistags.axisTypeCount(vigra.AxisType.Channels) == 0: treadKey = popFlagsFromTheKey(treadKey,axistags,'c') else: treadKey.insert(channelAxis, slice(None,None,None)) treadKey=tuple(treadKey) req = self.inputs["Input"][treadKey].allocate() sourceArray = req.wait() req.result = None req.destination = None if sourceArray.dtype != numpy.float32: sourceArrayF = sourceArray.astype(numpy.float32) sourceArray.resize((1,), refcheck = False) del sourceArray sourceArray = sourceArrayF sourceArrayV = sourceArray.view(vigra.VigraArray) sourceArrayV.axistags = copy.copy(axistags) dimCol = len(self.scales) dimRow = self.matrix.shape[0] sourceArraysForSigmas = [None]*dimCol #connect individual operators for j in range(dimCol): hasScale = False for i in range(dimRow): if self.matrix[i,j]: hasScale = True if not hasScale: continue destSigma = 1.0 if self.scales[j] > destSigma: tempSigma = math.sqrt(self.scales[j]**2 - destSigma**2) else: destSigma = 0.0 tempSigma = self.scales[j] vigOpSourceShape = list(vigOpSourceStop - vigOpSourceStart) if hasTimeAxis: if timeAxis < channelAxis: vigOpSourceShape.insert(timeAxis, ( oldstop - oldstart)[timeAxis]) else: vigOpSourceShape.insert(timeAxis-1, ( oldstop - oldstart)[timeAxis]) vigOpSourceShape.insert(channelAxis, inShape[channelAxis]) sourceArraysForSigmas[j] = numpy.ndarray(tuple(vigOpSourceShape),numpy.float32) for i,vsa in enumerate(sourceArrayV.timeIter()): droi = (tuple(vigOpSourceStart._asint()), tuple(vigOpSourceStop._asint())) tmp_key = getAllExceptAxis(len(sourceArraysForSigmas[j].shape),timeAxis, i) sourceArraysForSigmas[j][tmp_key] = vigra.filters.gaussianSmoothing(vsa,tempSigma, roi = droi, window_size = 3.5 ) else: droi = (tuple(vigOpSourceStart._asint()), tuple(vigOpSourceStop._asint())) #print droi, sourceArray.shape, tempSigma,self.scales[j] sourceArraysForSigmas[j] = vigra.filters.gaussianSmoothing(sourceArrayV, sigma = tempSigma, roi = droi, window_size = 3.5) #sourceArrayForSigma = sourceArrayForSigma.view(numpy.ndarray) del sourceArrayV try: sourceArray.resize((1,), refcheck = False) except ValueError: # Sometimes this fails, but that's okay. logger.debug("Failed to free array memory.") del sourceArray closures = [] #connect individual operators for i in range(dimRow): for j in range(dimCol): val=self.matrix[i,j] if val: vop= self.featureOps[i][j] oslot = vop.outputs["Output"] req = None inTagKeys = [ax.key for ax in oslot.meta.axistags] if flag in inTagKeys: slices = oslot.meta.shape[axisindex] if cnt + slices >= rroi.start[axisindex] and rroi.start[axisindex]-cnt<slices and rroi.start[axisindex]+written<rroi.stop[axisindex]: begin = 0 if cnt < rroi.start[axisindex]: begin = rroi.start[axisindex] - cnt end = slices if cnt + end > rroi.stop[axisindex]: end -= cnt + end - rroi.stop[axisindex] key_ = copy.copy(oldkey) key_.insert(axisindex, slice(begin, end, None)) reskey = [slice(None, None, None) for x in range(len(result.shape))] reskey[axisindex] = slice(written, written+end-begin, None) destArea = result[tuple(reskey)] roi_ = SubRegion(self.Input, pslice=key_) closure = partial(oslot.operator.execute, oslot, (), roi_, destArea, sourceArray = sourceArraysForSigmas[j]) closures.append(closure) written += end - begin cnt += slices else: if cnt>=rroi.start[axisindex] and rroi.start[axisindex] + written < rroi.stop[axisindex]: reskey = copy.copy(oldkey) reskey.insert(axisindex, written) #print "key: ", key, "reskey: ", reskey, "oldkey: ", oldkey #print "result: ", result.shape, "inslot:", inSlot.shape destArea = result[tuple(reskey)] logger.debug(oldkey, destArea.shape, sourceArraysForSigmas[j].shape) oldroi = SubRegion(self.Input, pslice=oldkey) closure = partial(oslot.operator.execute, oslot, (), oldroi, destArea, sourceArray = sourceArraysForSigmas[j]) closures.append(closure) written += 1 cnt += 1 pool = Pool() for c in closures: r = pool.request(c) pool.wait() pool.clean() for i in range(len(sourceArraysForSigmas)): if sourceArraysForSigmas[i] is not None: try: sourceArraysForSigmas[i].resize((1,)) except: sourceArraysForSigmas[i] = None