def derive_datasets(self, input_dataset_dict, stack_output_info, tile_type_info):
        assert type(input_dataset_dict) == dict, 'input_dataset_dict must be a dict'
        
        log_multiline(logger.debug, input_dataset_dict, 'input_dataset_dict', '\t')    

        output_dataset_dict = {}
        nbar_dataset_info = input_dataset_dict['NBAR'] # Only need NBAR data for NDVI
        
        nbar_dataset_path = nbar_dataset_info['tile_pathname']
        

        # Get a boolean mask from the PQA dataset (use default parameters for mask and dilation)
        pqa_mask = self.get_pqa_mask(input_dataset_dict['PQA']['tile_pathname']) 
        
        nbar_dataset = gdal.Open(nbar_dataset_path)
        assert nbar_dataset, 'Unable to open dataset %s' % nbar_dataset
        logger.debug('Opened NBAR dataset %s', nbar_dataset_path)
        
        #no_data_value = nbar_dataset_info['nodata_value']
        no_data_value = -32767 # Need a value outside the scaled range -10000 - +10000
                                
        output_stack_path = os.path.join(self.output_dir, 'NDVI_pqa_masked.vrt')
                
        output_tile_path = os.path.join(self.output_dir, re.sub('\.\w+$', 
                                                               (tile_type_info['file_extension']) % '_NDVI%s',
                                                               os.path.basename(nbar_dataset_path)
                                                               )
                                       )
            
        # Copy metadata for eventual inclusion in stack file output
        # This could also be written to the output tile if required
        output_dataset_info = dict(nbar_dataset_info)
        output_dataset_info['tile_pathname'] = output_tile_path # This is the most important modification - used to find 
        output_dataset_info['band_name'] = 'NDVI with PQA mask applied'
        output_dataset_info['band_tag'] = 'NDVI-PQA'
        output_dataset_info['tile_layer'] = 1

        # NBAR bands into 2D NumPy arrays. 
        near_ir_band_data = nbar_dataset.GetRasterBand(4).ReadAsArray() # Near Infrared light
        visible_band_data = nbar_dataset.GetRasterBand(3).ReadAsArray() # Red Visible Light
        
        logger.debug('near_ir_band_data = %s', near_ir_band_data)
        logger.debug('visible_band_data = %s', visible_band_data)
        logger.debug('SCALE_FACTOR = %s', SCALE_FACTOR)

        # Calculate NDVI for every element in the array using
        # ((NIR - VIS) / (NIR + VIS)) * SCALE_FACTOR
        # HINT - Use numpy.true_divide(numerator, denominator) to avoid divide by 0 errors
        data_array = numpy.true_divide(near_ir_band_data - visible_band_data, (near_ir_band_data + visible_band_data)) * SCALE_FACTOR
        
        
        self.apply_pqa_mask(data_array, pqa_mask, no_data_value)
        
        # Create our output file
        gdal_driver = gdal.GetDriverByName(tile_type_info['file_format'])
        output_dataset = gdal_driver.Create(output_tile_path, 
                                            nbar_dataset.RasterXSize, nbar_dataset.RasterYSize,
                                            1, nbar_dataset.GetRasterBand(1).DataType,
                                            tile_type_info['format_options'].split(','))
        assert output_dataset, 'Unable to open output dataset %s'% output_dataset                                   
        output_dataset.SetGeoTransform(nbar_dataset.GetGeoTransform())
        output_dataset.SetProjection(nbar_dataset.GetProjection()) 
        output_band = output_dataset.GetRasterBand(1)
        output_band.WriteArray(data_array)
        output_band.SetNoDataValue(no_data_value)
        output_band.FlushCache()
        
        # This is not strictly necessary - copy metadata to output dataset
        output_dataset_metadata = nbar_dataset.GetMetadata()
        if output_dataset_metadata:
            output_dataset.SetMetadata(output_dataset_metadata) 
            log_multiline(logger.debug, output_dataset_metadata, 'output_dataset_metadata', '\t')    
        
        output_dataset.FlushCache()
        logger.info('Finished writing %s', output_tile_path)
        
        output_dataset_dict[output_stack_path] = output_dataset_info

        # NDVI dataset processed - return info
        return output_dataset_dict
dataset/ETHPy150Open GeoscienceAustralia/agdc/contrib/agdc_workshop_exercises/ndvi_analysis_stacker-finished.py/NDVIStacker.derive_datasets/swapped operands of `%`