//  [python]
def _valStep(self, data, layerIdx):
        data = self._datasetLayerTransform(
            data, self.normLayers[layerIdx], 0, 0, 0, 0, 0)

        #channel zeroing
        if 'channelMask' in self.args.keys():
            maskedFeatures = data['inputFeatures'] * tf.constant(np.array(self.args['channelMask'])[np.newaxis, np.newaxis, :], dtype=tf.float32)
            print('masking')
        else:
            maskedFeatures = data['inputFeatures']
            
        inputTransformedFeatures = self.inputLayers[layerIdx](
            maskedFeatures, training=False)

        predictions = self.model(inputTransformedFeatures, training=False)

        batchSize = tf.shape(data['seqClassIDs'])[0]
        if self.args['lossType'] == 'ctc':
            sparseLabels = tf.cast(tf.sparse.from_dense(
                data['seqClassIDs']), dtype=tf.int32)
            sparseLabels = tf.sparse.SparseTensor(
                indices=sparseLabels.indices,
                values=sparseLabels.values-1,
                dense_shape=[batchSize, self.args['dataset']['maxSeqElements']])

            nTimeSteps = self.model.getSubsampledTimeSteps(data['nTimeSteps'])
            pred_loss = tf.compat.v1.nn.ctc_loss_v2(sparseLabels, predictions,
                                                    tf.cast(
                                                        data['nSeqElements'], dtype=tf.int32), nTimeSteps,
                                                    logits_time_major=False, unique=None, blank_index=-1, name=None)

            pred_loss = tf.reduce_mean(pred_loss)

        elif self.args['lossType'] == 'ce':
            mask = tf.tile(data['ceMask'][:, :, tf.newaxis], [
                                1, 1, self.args['dataset']['nClasses']])
            ceLoss = tf.keras.losses.CategoricalCrossentropy(
                from_logits=True)
            pred_loss = ceLoss(
                data['classLabelsOneHot'][:,:,0:-1], predictions[:, :, 0:-1]*mask)
            pred_loss = tf.reduce_mean(pred_loss)
            newClassSignalError = tf.reduce_mean(tf.math.square(tf.math.sigmoid(predictions[:,:,-1]) - data['newClassSignal']))
            pred_loss += newClassSignalError

            nTimeSteps = self.model.getSubsampledTimeSteps(data['nTimeSteps'])

        if self.args['lossType'] == 'ctc':
            sparseLabels = tf.cast(tf.sparse.from_dense(
                data['seqClassIDs']), dtype=tf.int32)
            sparseLabels = tf.sparse.SparseTensor(
                indices=sparseLabels.indices,
                values=sparseLabels.values-1,
                dense_shape=[batchSize, self.args['dataset']['maxSeqElements']])

            decodedStrings, _ = tf.nn.ctc_greedy_decoder(tf.transpose(predictions, [1, 0, 2]),
                                                         nTimeSteps,
                                                         merge_repeated=True)
            editDistance = tf.edit_distance(decodedStrings[0], tf.cast(
                sparseLabels, tf.int64), normalize=False)
            seqErrorRate = tf.cast(tf.reduce_sum(editDistance), dtype=tf.float32)/tf.cast(
                tf.reduce_sum(data['nSeqElements']), dtype=tf.float32)
        else:
            indices = tf.math.argmax(predictions[:,:,0:-1],axis=-1)
            onehotPreds = tf.one_hot(indices, self.args['dataset']['nClasses'])
            label_err  = tf.math.reduce_mean(tf.math.abs((tf.cast(data['classLabelsOneHot'][:,:,0:-1], dtype=tf.float32) - tf.cast(onehotPreds, dtype=tf.float32))))
            newsig_err = tf.reduce_mean(tf.math.abs((tf.cast(data['newClassSignal'],dtype=tf.float32)   - tf.cast(predictions[:,:,-1], dtype=tf.float32))))
            decodedStrings = [tf.sparse.SparseTensor(
                indices=[[0, 0]], values=[tf.constant(1, dtype=tf.int64)], dense_shape=[2, 2])]
            seqErrorRate = label_err #+ newsig_err
            editDistance = 0.0
        output = {}
        output['logits'] = predictions
        output['decodedStrings'] = decodedStrings
        output['seqErrorRate'] = seqErrorRate
        output['editDistance'] = editDistance
        output['trueSeq'] = data['seqClassIDs']
        output['nSeqElements'] = data['nSeqElements']
        output['transcription'] = data['transcription']
        output['logitLengths'] = nTimeSteps

        return output