def testBasic(self): graph = Graph() op1 = OpMultiPassthrough(graph=graph) opTranspose = OpTransposeSlots(graph=graph) opTranspose.Inputs.connect( op1.Outputs ) opTranspose.OutputLength.setValue( 2 ) assert len( opTranspose.Outputs ) == 2 op1.Inputs.resize( 3 ) assert len( op1.Outputs ) == 3 assert len( opTranspose.Outputs[0] ) == 3 op1.Inputs[0].resize(2) op1.Inputs[0][0].setValue( (0,0) ) # Sanity check... assert op1.Outputs[0][0].ready() assert op1.Outputs[0][0].value == (0,0) assert opTranspose.Outputs[0][0].ready() assert opTranspose.Outputs[0][0].value == (0,0) op1.Inputs[0][1].setValue( (0,1) ) # Sanity check... assert op1.Outputs[0][1].ready() assert op1.Outputs[0][1].value == (0,1) assert opTranspose.Outputs[1][0].ready() assert opTranspose.Outputs[1][0].value == (0,1) op1.Inputs[2].resize(2) op1.Inputs[2][0].setValue( (2,0) ) # Sanity check... assert op1.Outputs[2][0].ready() assert op1.Outputs[2][0].value == (2,0) assert opTranspose.Outputs[0][2].ready() assert opTranspose.Outputs[0][2].value == (2,0) op1.Inputs[2][1].setValue( (2,1) ) # Sanity check... assert op1.Outputs[2][1].ready() assert op1.Outputs[2][1].value == (2,1) assert opTranspose.Outputs[1][2].ready() assert opTranspose.Outputs[1][2].value == (2,1) # The middle input multi-slot was never configured. # Therefore, the middle slot of each multi-output is not ready. assert not opTranspose.Outputs[0,1].ready() assert not opTranspose.Outputs[1,1].ready()
def _initBatchWorkflow(self): """ Connect the batch-mode top-level operators to the training workflow and to each other. """ # Access applet operators from the training workflow opTrainingDataSelection = self.dataSelectionApplet.topLevelOperator opTrainingFeatures = self.featureSelectionApplet.topLevelOperator opClassify = self.pcApplet.topLevelOperator # Access the batch operators opBatchInputs = self.batchInputApplet.topLevelOperator opBatchResults = self.batchResultsApplet.topLevelOperator opBatchInputs.DatasetRoles.connect( opTrainingDataSelection.DatasetRoles ) opSelectFirstLane = OperatorWrapper( OpSelectSubslot, parent=self ) opSelectFirstLane.Inputs.connect( opTrainingDataSelection.ImageGroup ) opSelectFirstLane.SubslotIndex.setValue(0) opSelectFirstRole = OpSelectSubslot( parent=self ) opSelectFirstRole.Inputs.connect( opSelectFirstLane.Output ) opSelectFirstRole.SubslotIndex.setValue(self.DATA_ROLE_RAW) opBatchResults.ConstraintDataset.connect( opSelectFirstRole.Output ) ## Create additional batch workflow operators opBatchFeatures = OperatorWrapper( OpFeatureSelectionNoCache, operator_kwargs={'filter_implementation': self.filter_implementation}, parent=self, promotedSlotNames=['InputImage'] ) opBatchPredictionPipeline = OperatorWrapper( OpPredictionPipelineNoCache, parent=self ) ## Connect Operators ## opTranspose = OpTransposeSlots( parent=self ) opTranspose.OutputLength.setValue(2) # There are 2 roles opTranspose.Inputs.connect( opBatchInputs.DatasetGroup ) opTranspose.name = "batchTransposeInputs" # Provide dataset paths from data selection applet to the batch export applet opBatchResults.RawDatasetInfo.connect( opTranspose.Outputs[self.DATA_ROLE_RAW] ) opBatchResults.WorkingDirectory.connect( opBatchInputs.WorkingDirectory ) # Connect (clone) the feature operator inputs from # the interactive workflow's features operator (which gets them from the GUI) opBatchFeatures.Scales.connect( opTrainingFeatures.Scales ) opBatchFeatures.FeatureIds.connect( opTrainingFeatures.FeatureIds ) opBatchFeatures.SelectionMatrix.connect( opTrainingFeatures.SelectionMatrix ) # Classifier and NumClasses are provided by the interactive workflow opBatchPredictionPipeline.Classifier.connect( opClassify.Classifier ) opBatchPredictionPipeline.NumClasses.connect( opClassify.NumClasses ) # Provide these for the gui opBatchResults.RawData.connect( opBatchInputs.Image ) opBatchResults.PmapColors.connect( opClassify.PmapColors ) opBatchResults.LabelNames.connect( opClassify.LabelNames ) # Connect Image pathway: # Input Image -> Features Op -> Prediction Op -> Export opBatchFeatures.InputImage.connect( opBatchInputs.Image ) opBatchPredictionPipeline.PredictionMask.connect( opBatchInputs.Image1 ) opBatchPredictionPipeline.FeatureImages.connect( opBatchFeatures.OutputImage ) opBatchResults.SelectionNames.setValue( self.EXPORT_NAMES ) # opBatchResults.Inputs is indexed by [lane][selection], # Use OpTranspose to allow connection. opTransposeBatchInputs = OpTransposeSlots( parent=self ) opTransposeBatchInputs.name = "opTransposeBatchInputs" opTransposeBatchInputs.OutputLength.setValue(0) opTransposeBatchInputs.Inputs.resize( len(self.EXPORT_NAMES) ) opTransposeBatchInputs.Inputs[0].connect( opBatchPredictionPipeline.HeadlessPredictionProbabilities ) # selection 0 opTransposeBatchInputs.Inputs[1].connect( opBatchPredictionPipeline.SimpleSegmentation ) # selection 1 opTransposeBatchInputs.Inputs[2].connect( opBatchPredictionPipeline.HeadlessUncertaintyEstimate ) # selection 2 opTransposeBatchInputs.Inputs[3].connect( opBatchPredictionPipeline.FeatureImages ) # selection 3 for slot in opTransposeBatchInputs.Inputs: assert slot.partner is not None # Now opTransposeBatchInputs.Outputs is level-2 indexed by [lane][selection] opBatchResults.Inputs.connect( opTransposeBatchInputs.Outputs ) # We don't actually need the cached path in the batch pipeline. # Just connect the uncached features here to satisfy the operator. #opBatchPredictionPipeline.CachedFeatureImages.connect( opBatchFeatures.OutputImage ) self.opBatchFeatures = opBatchFeatures self.opBatchPredictionPipeline = opBatchPredictionPipeline
def _initBatchWorkflow(self): """ Connect the batch-mode top-level operators to the training workflow and to each other. """ # Access applet operators from the training workflow opTrainingDataSelection = self.dataSelectionApplet.topLevelOperator opTrainingFeatures = self.featureSelectionApplet.topLevelOperator opClassify = self.pcApplet.topLevelOperator # Access the batch operators opBatchInputs = self.batchInputApplet.topLevelOperator opBatchResults = self.batchResultsApplet.topLevelOperator opBatchInputs.DatasetRoles.connect( opTrainingDataSelection.DatasetRoles) opSelectFirstLane = OperatorWrapper(OpSelectSubslot, parent=self) opSelectFirstLane.Inputs.connect(opTrainingDataSelection.ImageGroup) opSelectFirstLane.SubslotIndex.setValue(0) opSelectFirstRole = OpSelectSubslot(parent=self) opSelectFirstRole.Inputs.connect(opSelectFirstLane.Output) opSelectFirstRole.SubslotIndex.setValue(self.DATA_ROLE_RAW) opBatchResults.ConstraintDataset.connect(opSelectFirstRole.Output) ## Create additional batch workflow operators opBatchFeatures = OperatorWrapper(OpFeatureSelectionNoCache, operator_kwargs={ 'filter_implementation': self.filter_implementation }, parent=self, promotedSlotNames=['InputImage']) opBatchPredictionPipeline = OperatorWrapper( OpPredictionPipelineNoCache, parent=self) ## Connect Operators ## opTranspose = OpTransposeSlots(parent=self) opTranspose.OutputLength.setValue(2) # There are 2 roles opTranspose.Inputs.connect(opBatchInputs.DatasetGroup) opTranspose.name = "batchTransposeInputs" # Provide dataset paths from data selection applet to the batch export applet opBatchResults.RawDatasetInfo.connect( opTranspose.Outputs[self.DATA_ROLE_RAW]) opBatchResults.WorkingDirectory.connect(opBatchInputs.WorkingDirectory) # Connect (clone) the feature operator inputs from # the interactive workflow's features operator (which gets them from the GUI) opBatchFeatures.Scales.connect(opTrainingFeatures.Scales) opBatchFeatures.FeatureIds.connect(opTrainingFeatures.FeatureIds) opBatchFeatures.SelectionMatrix.connect( opTrainingFeatures.SelectionMatrix) # Classifier and NumClasses are provided by the interactive workflow opBatchPredictionPipeline.Classifier.connect(opClassify.Classifier) opBatchPredictionPipeline.NumClasses.connect(opClassify.NumClasses) # Provide these for the gui opBatchResults.RawData.connect(opBatchInputs.Image) opBatchResults.PmapColors.connect(opClassify.PmapColors) opBatchResults.LabelNames.connect(opClassify.LabelNames) # Connect Image pathway: # Input Image -> Features Op -> Prediction Op -> Export opBatchFeatures.InputImage.connect(opBatchInputs.Image) opBatchPredictionPipeline.PredictionMask.connect(opBatchInputs.Image1) opBatchPredictionPipeline.FeatureImages.connect( opBatchFeatures.OutputImage) opBatchResults.SelectionNames.setValue(self.EXPORT_NAMES) # opBatchResults.Inputs is indexed by [lane][selection], # Use OpTranspose to allow connection. opTransposeBatchInputs = OpTransposeSlots(parent=self) opTransposeBatchInputs.name = "opTransposeBatchInputs" opTransposeBatchInputs.OutputLength.setValue(0) opTransposeBatchInputs.Inputs.resize(len(self.EXPORT_NAMES)) opTransposeBatchInputs.Inputs[0].connect( opBatchPredictionPipeline.HeadlessPredictionProbabilities ) # selection 0 opTransposeBatchInputs.Inputs[1].connect( opBatchPredictionPipeline.SimpleSegmentation) # selection 1 opTransposeBatchInputs.Inputs[2].connect( opBatchPredictionPipeline.HeadlessUncertaintyEstimate ) # selection 2 opTransposeBatchInputs.Inputs[3].connect( opBatchPredictionPipeline.FeatureImages) # selection 3 for slot in opTransposeBatchInputs.Inputs: assert slot.partner is not None # Now opTransposeBatchInputs.Outputs is level-2 indexed by [lane][selection] opBatchResults.Inputs.connect(opTransposeBatchInputs.Outputs) # We don't actually need the cached path in the batch pipeline. # Just connect the uncached features here to satisfy the operator. #opBatchPredictionPipeline.CachedFeatureImages.connect( opBatchFeatures.OutputImage ) self.opBatchFeatures = opBatchFeatures self.opBatchPredictionPipeline = opBatchPredictionPipeline
def _initBatchWorkflow(self): """ Connect the batch-mode top-level operators to the training workflow and to eachother. """ # Access applet operators from the training workflow opTrainingDataSelection = self.dataSelectionApplet.topLevelOperator opTrainingFeatures = self.featureSelectionApplet.topLevelOperator opClassify = self.countingApplet.topLevelOperator opSelectFirstLane = OperatorWrapper( OpSelectSubslot, parent=self ) opSelectFirstLane.Inputs.connect( opTrainingDataSelection.ImageGroup ) opSelectFirstLane.SubslotIndex.setValue(0) opSelectFirstRole = OpSelectSubslot( parent=self ) opSelectFirstRole.Inputs.connect( opSelectFirstLane.Output ) opSelectFirstRole.SubslotIndex.setValue(0) ## Create additional batch workflow operators opBatchFeatures = OperatorWrapper( OpFeatureSelection, operator_kwargs={'filter_implementation':'Original'}, parent=self, promotedSlotNames=['InputImage'] ) opBatchPredictionPipeline = OperatorWrapper( OpPredictionPipeline, parent=self ) # Create applets for batch workflow self.batchInputApplet = DataSelectionApplet(self, "Batch Prediction Input Selections", "BatchDataSelection", supportIlastik05Import=False, batchDataGui=True) self.batchResultsApplet = CountingDataExportApplet(self, "Batch Prediction Output Locations", opBatchPredictionPipeline, isBatch=True) # Expose in shell self._applets.append(self.batchInputApplet) self._applets.append(self.batchResultsApplet) opBatchInputs = self.batchInputApplet.topLevelOperator opBatchResults = self.batchResultsApplet.topLevelOperator opBatchInputs.DatasetRoles.connect( opTrainingDataSelection.DatasetRoles ) opBatchResults.ConstraintDataset.connect( opSelectFirstRole.Output ) ## Connect Operators ## opTranspose = OpTransposeSlots( parent=self ) opTranspose.OutputLength.setValue(1) opTranspose.Inputs.connect( opBatchInputs.DatasetGroup ) # Provide dataset paths from data selection applet to the batch export applet opBatchResults.RawDatasetInfo.connect( opTranspose.Outputs[0] ) opBatchResults.WorkingDirectory.connect( opBatchInputs.WorkingDirectory ) # Connect (clone) the feature operator inputs from # the interactive workflow's features operator (which gets them from the GUI) opBatchFeatures.Scales.connect( opTrainingFeatures.Scales ) opBatchFeatures.FeatureIds.connect( opTrainingFeatures.FeatureIds ) opBatchFeatures.SelectionMatrix.connect( opTrainingFeatures.SelectionMatrix ) # Classifier and LabelsCount are provided by the interactive workflow opBatchPredictionPipeline.Classifier.connect( opClassify.Classifier ) opBatchPredictionPipeline.MaxLabel.connect( opClassify.MaxLabelValue ) opBatchPredictionPipeline.FreezePredictions.setValue( False ) # Provide these for the gui opBatchResults.RawData.connect( opBatchInputs.Image ) opBatchResults.PmapColors.connect( opClassify.PmapColors ) opBatchResults.LabelNames.connect( opClassify.LabelNames ) opBatchResults.UpperBound.connect( opClassify.UpperBound ) # Connect Image pathway: # Input Image -> Features Op -> Prediction Op -> Export opBatchFeatures.InputImage.connect( opBatchInputs.Image ) opBatchPredictionPipeline.FeatureImages.connect( opBatchFeatures.OutputImage ) opBatchResults.SelectionNames.setValue( ['Probabilities'] ) # opBatchResults.Inputs is indexed by [lane][selection], # Use OpTranspose to allow connection. opTransposeBatchInputs = OpTransposeSlots( parent=self ) opTransposeBatchInputs.OutputLength.setValue(0) opTransposeBatchInputs.Inputs.resize(1) opTransposeBatchInputs.Inputs[0].connect( opBatchPredictionPipeline.HeadlessPredictionProbabilities ) # selection 0 # Now opTransposeBatchInputs.Outputs is level-2 indexed by [lane][selection] opBatchResults.Inputs.connect( opTransposeBatchInputs.Outputs ) # We don't actually need the cached path in the batch pipeline. # Just connect the uncached features here to satisfy the operator. opBatchPredictionPipeline.CachedFeatureImages.connect( opBatchFeatures.OutputImage ) self.opBatchPredictionPipeline = opBatchPredictionPipeline
def _initBatchWorkflow(self): # If we are in pixel workflow, start from raw data # The part below is simply copied from the pixel classification # Access applet operators from the training workflow opPixelTrainingDataSelection = self.dataSelectionApplet.topLevelOperator opPixelTrainingFeatures = self.featureSelectionApplet.topLevelOperator opPixelClassify = self.pcApplet.topLevelOperator # Access the batch operators opBatchInputs = self.dataSelectionAppletBatch.topLevelOperator opBatchExport = self.batchExportApplet.topLevelOperator opBatchInputs.DatasetRoles.connect( opPixelTrainingDataSelection.DatasetRoles ) opSelectFirstLane = OperatorWrapper( OpSelectSubslot, parent=self ) opSelectFirstLane.Inputs.connect( opPixelTrainingDataSelection.ImageGroup ) opSelectFirstLane.SubslotIndex.setValue(0) opSelectFirstRole = OpSelectSubslot( parent=self ) opSelectFirstRole.Inputs.connect( opSelectFirstLane.Output ) opSelectFirstRole.SubslotIndex.setValue(0) ## Create additional batch workflow operators # FIXME: this should take the same filter_implementation as the pixel operator!!! opBatchPixelFeatures = OperatorWrapper( OpFeatureSelection, operator_kwargs={'filter_implementation':'Original'}, parent=self, promotedSlotNames=['InputImage'] ) opBatchPixelPredictionPipeline = OperatorWrapper( OpPredictionPipeline, parent=self ) # Connect (clone) the feature operator inputs from # the interactive workflow's features operator (which gets them from the GUI) opBatchPixelFeatures.Scales.connect( opPixelTrainingFeatures.Scales ) opBatchPixelFeatures.FeatureIds.connect( opPixelTrainingFeatures.FeatureIds ) opBatchPixelFeatures.SelectionMatrix.connect( opPixelTrainingFeatures.SelectionMatrix ) # Classifier and LabelsCount are provided by the interactive workflow opBatchPixelPredictionPipeline.Classifier.connect( opPixelClassify.Classifier ) opBatchPixelPredictionPipeline.NumClasses.connect( opPixelClassify.NumClasses ) opBatchPixelPredictionPipeline.FreezePredictions.setValue( False ) # Connect Image pathway: # Input Image -> Features Op -> Prediction Op -> Thresholding opBatchPixelFeatures.InputImage.connect( opBatchInputs.Image ) opBatchPixelPredictionPipeline.FeatureImages.connect( opBatchPixelFeatures.OutputImage ) # We don't actually need the cached path in the batch pipeline. # Just connect the uncached features here to satisfy the operator. opBatchPixelPredictionPipeline.CachedFeatureImages.connect( opBatchPixelFeatures.OutputImage ) # Now connect the object part opObjectTrainingTopLevel = self.objectClassificationApplet.topLevelOperator opBlockwiseObjectClassification = self.blockwiseObjectClassificationApplet.topLevelOperator op5Raw = OperatorWrapper(OpReorderAxes, parent=self) if self.fillMissing != 'none': opBatchFillMissingSlices = OperatorWrapper(OpFillMissingSlicesNoCache, parent=self) opBatchFillMissingSlices.Input.connect(opBatchInputs.Image) op5Raw.Input.connect(opBatchFillMissingSlices.Output) else: op5Raw.Input.connect(opBatchInputs.Image) opInteractiveThreshold = self.thresholdingApplet.topLevelOperator opBatchThreshold = OperatorWrapper(OpThresholdTwoLevels, parent=self) opBatchThreshold.MinSize.connect(opInteractiveThreshold.MinSize) opBatchThreshold.MaxSize.connect(opInteractiveThreshold.MaxSize) opBatchThreshold.HighThreshold.connect(opInteractiveThreshold.HighThreshold) opBatchThreshold.LowThreshold.connect(opInteractiveThreshold.LowThreshold) opBatchThreshold.SingleThreshold.connect(opInteractiveThreshold.SingleThreshold) opBatchThreshold.SmootherSigma.connect(opInteractiveThreshold.SmootherSigma) opBatchThreshold.Channel.connect(opInteractiveThreshold.Channel) opBatchThreshold.CurOperator.connect(opInteractiveThreshold.CurOperator) # Image pathway is from the batch pipeline op5Pred = OperatorWrapper(OpReorderAxes, parent=self) op5Pred.Input.connect(opBatchPixelPredictionPipeline.HeadlessPredictionProbabilities) op5Binary = OperatorWrapper(OpReorderAxes, parent=self) opBatchThreshold.RawInput.connect(op5Raw.Output) opBatchThreshold.InputImage.connect(op5Pred.Output) op5Binary.Input.connect(opBatchThreshold.Output) # BATCH outputs are computed BLOCKWISE. # Connect the blockwise classification operator # Parameter inputs are cloned from the interactive workflow, opBatchObjectClassify = OperatorWrapper(OpBlockwiseObjectClassification, parent=self, promotedSlotNames=['RawImage', 'BinaryImage']) opBatchObjectClassify.Classifier.connect(opObjectTrainingTopLevel.Classifier) opBatchObjectClassify.LabelsCount.connect(opObjectTrainingTopLevel.NumLabels) opBatchObjectClassify.SelectedFeatures.connect(opObjectTrainingTopLevel.SelectedFeatures) opBatchObjectClassify.BlockShape3dDict.connect(opBlockwiseObjectClassification.BlockShape3dDict) opBatchObjectClassify.HaloPadding3dDict.connect(opBlockwiseObjectClassification.HaloPadding3dDict) opBatchObjectClassify.RawImage.connect(op5Raw.Output) opBatchObjectClassify.BinaryImage.connect(op5Binary.Output) self.opBatchClassify = opBatchObjectClassify # We need to transpose the dataset group, because it is indexed by [image_index][group_index] # But we want it to be indexed by [group_index][image_index] for the RawDatasetInfo connection, below. opTransposeDatasetGroup = OpTransposeSlots( parent=self ) opTransposeDatasetGroup.OutputLength.setValue(1) opTransposeDatasetGroup.Inputs.connect( opBatchInputs.DatasetGroup ) # Connect the batch OUTPUT applet opBatchExport.RawData.connect( opBatchInputs.Image ) opBatchExport.RawDatasetInfo.connect( opTransposeDatasetGroup.Outputs[0] ) # See EXPORT_SELECTION_PREDICTIONS, EXPORT_SELECTION_PROBABILITIES, and EXPORT_SELECTION_PIXEL_PROBABILITIES, above opBatchExport.SelectionNames.setValue( ['Object Predictions', 'Object Probabilities', 'Pixel Probabilities'] ) # opBatchResults.Inputs is indexed by [lane][selection], # Use OpTranspose to allow connection. opTransposeBatchInputs = OpTransposeSlots( parent=self ) opTransposeBatchInputs.OutputLength.setValue(0) opTransposeBatchInputs.Inputs.resize(3) opTransposeBatchInputs.Inputs[EXPORT_SELECTION_PREDICTIONS].connect( opBatchObjectClassify.PredictionImage ) # selection 0 opTransposeBatchInputs.Inputs[EXPORT_SELECTION_PROBABILITIES].connect( opBatchObjectClassify.ProbabilityChannelImage ) # selection 1 opTransposeBatchInputs.Inputs[EXPORT_SELECTION_PIXEL_PROBABILITIES].connect( opBatchThreshold.InputImage ) # selection 2 (must use op5'd version) # Now opTransposeBatchInputs.Outputs is level-2 indexed by [lane][selection] opBatchExport.Inputs.connect( opTransposeBatchInputs.Outputs )
def _initBatchWorkflow(self): # Access applet operators from the training workflow opObjectTrainingTopLevel = self.objectClassificationApplet.topLevelOperator opBlockwiseObjectClassification = self.blockwiseObjectClassificationApplet.topLevelOperator # If we are not in the binary workflow, connect the thresholding operator. # Parameter inputs are cloned from the interactive workflow, if isinstance(self, ObjectClassificationWorkflowBinary): #FIXME pass else: opInteractiveThreshold = self.thresholdingApplet.topLevelOperator opBatchThreshold = OperatorWrapper(OpThresholdTwoLevels, parent=self) opBatchThreshold.MinSize.connect(opInteractiveThreshold.MinSize) opBatchThreshold.MaxSize.connect(opInteractiveThreshold.MaxSize) opBatchThreshold.HighThreshold.connect(opInteractiveThreshold.HighThreshold) opBatchThreshold.LowThreshold.connect(opInteractiveThreshold.LowThreshold) opBatchThreshold.SingleThreshold.connect(opInteractiveThreshold.SingleThreshold) opBatchThreshold.SmootherSigma.connect(opInteractiveThreshold.SmootherSigma) opBatchThreshold.Channel.connect(opInteractiveThreshold.Channel) opBatchThreshold.CurOperator.connect(opInteractiveThreshold.CurOperator) # OpDataSelectionGroup.ImageGroup is indexed by [laneIndex][roleIndex], # but we need a slot that is indexed by [roleIndex][laneIndex] # so we can pass each role to the appropriate slots. # We use OpTransposeSlots to do this. opBatchInputByRole = OpTransposeSlots( parent=self ) opBatchInputByRole.Inputs.connect( self.opDataSelectionBatch.ImageGroup ) opBatchInputByRole.OutputLength.setValue(2) # Lane-indexed multislot for raw data batchInputsRaw = opBatchInputByRole.Outputs[0] # Lane-indexed multislot for binary/prediction-map data batchInputsOther = opBatchInputByRole.Outputs[1] # Connect the blockwise classification operator # Parameter inputs are cloned from the interactive workflow, opBatchClassify = OperatorWrapper(OpBlockwiseObjectClassification, parent=self, promotedSlotNames=['RawImage', 'BinaryImage']) opBatchClassify.Classifier.connect(opObjectTrainingTopLevel.Classifier) opBatchClassify.LabelsCount.connect(opObjectTrainingTopLevel.NumLabels) opBatchClassify.SelectedFeatures.connect(opObjectTrainingTopLevel.SelectedFeatures) opBatchClassify.BlockShape3dDict.connect(opBlockwiseObjectClassification.BlockShape3dDict) opBatchClassify.HaloPadding3dDict.connect(opBlockwiseObjectClassification.HaloPadding3dDict) # but image pathway is from the batch pipeline op5Raw = OperatorWrapper(OpReorderAxes, parent=self) if self.fillMissing != 'none': opBatchFillMissingSlices = OperatorWrapper(OpFillMissingSlicesNoCache, parent=self) opBatchFillMissingSlices.Input.connect(batchInputsRaw) op5Raw.Input.connect(opBatchFillMissingSlices.Output) else: op5Raw.Input.connect(batchInputsRaw) op5Binary = OperatorWrapper(OpReorderAxes, parent=self) if self.input_types != 'raw+binary': op5Pred = OperatorWrapper(OpReorderAxes, parent=self) op5Pred.Input.connect(batchInputsOther) opBatchThreshold.RawInput.connect(op5Raw.Output) opBatchThreshold.InputImage.connect(op5Pred.Output) op5Binary.Input.connect(opBatchThreshold.Output) else: op5Binary.Input.connect(batchInputsOther) opBatchClassify.RawImage.connect(op5Raw.Output) opBatchClassify.BinaryImage.connect(op5Binary.Output) self.opBatchClassify = opBatchClassify # We need to transpose the dataset group, because it is indexed by [image_index][group_index] # But we want it to be indexed by [group_index][image_index] for the RawDatasetInfo connection, below. opTransposeDatasetGroup = OpTransposeSlots( parent=self ) opTransposeDatasetGroup.OutputLength.setValue(1) opTransposeDatasetGroup.Inputs.connect( self.opDataSelectionBatch.DatasetGroup ) # Connect the batch OUTPUT applet opBatchExport = self.batchExportApplet.topLevelOperator opBatchExport.RawData.connect( batchInputsRaw ) opBatchExport.RawDatasetInfo.connect( opTransposeDatasetGroup.Outputs[0] ) # See EXPORT_SELECTION_PREDICTIONS and EXPORT_SELECTION_PROBABILITIES, above opBatchExport.SelectionNames.setValue( ['Object Predictions', 'Object Probabilities'] ) # opBatchResults.Inputs is indexed by [lane][selection], # Use OpTranspose to allow connection. opTransposeBatchInputs = OpTransposeSlots( parent=self ) opTransposeBatchInputs.OutputLength.setValue(0) opTransposeBatchInputs.Inputs.resize(2) opTransposeBatchInputs.Inputs[EXPORT_SELECTION_PREDICTIONS].connect( opBatchClassify.PredictionImage ) # selection 0 opTransposeBatchInputs.Inputs[EXPORT_SELECTION_PROBABILITIES].connect( opBatchClassify.ProbabilityChannelImage ) # selection 1 # Now opTransposeBatchInputs.Outputs is level-2 indexed by [lane][selection] opBatchExport.Inputs.connect( opTransposeBatchInputs.Outputs )