# frozen_string_literal: true # Satellite LandSat8 # 30m de resolução # Banda 2 = Azul # Banda 3 = Verde # Banda 4 = Vermelho: 640-690 nm # Banda 5 = Infravermelho próximo: 850-880 nm module Satellite module Landsat8 class ImageryService AWS_URL = 's3://landsat-pds/c1/L8' attr_accessor :scene, :quantity # $scene = { path: '000', row: '000' } def initialize(scene, quantity = 2) self.scene = "#{scene[:path]}/#{scene[:row]}" self.quantity = quantity end def download_and_proccess Rails.logger.info "[Landsat8 | #{scene}] Listando últimos #{quantity} arquivos..." files = last Rails.logger.info "[Landsat8 | #{scene}] Checando arquivos que precisam ser baixados..." files.reject!{ |file| scene_already_proccessed?(file) } Rails.logger.info "[Landsat8 | #{scene}] Baixando #{files.length} cenas..." files.each_with_index do |file, index| Rails.logger.info "[Landsat8 | #{scene}] Fazendo download da cena do dia #{file[:date]}..." useful_files(file[:file]).map do |useful_file| Thread.new { Rails.logger.info "[Landsat8 | #{scene}] Fazendo download do arquivo #{useful_file}..." `aws s3 cp #{AWS_URL}/#{scene}/#{file[:file]}/#{useful_file} "#{output_path}/#{file[:file]}/#{useful_file}"` raise 'Error to execute aws s3 cp' unless $?.success? } end.map(&:join) Rails.logger.info "[Landsat8 | #{scene}] Processando arquivos #{index.next}/#{files.length}." Satellite::ImageryProccessor.new(band_object(file[:file])).proccess end end def last @lasts ||= `aws s3 ls #{AWS_URL}/#{scene}/` .split("\n") .select{ |file| file.end_with?('_RT/') } # Seleciona somente REAL TIME files - https://landsat.usgs.gov/landsat-collections .map do |name| name = name[/.*(LC08.+)\//,1] date = name[/.+?_.+?_.+?_(.+?)_/, 1].to_date { file: name, date: date } end .sort_by{ |item| item[:date] } .last(quantity) .reverse end def useful_files(file_path) all_files_from_last_scene = `aws s3 ls #{AWS_URL}/#{scene}/#{file_path}/` all_files_from_last_scene.split("\n").inject([]) do |useful_files, current_file| filtered_file = current_file[/.*(LC08.+(B[2-5].TIF|.jpg|MTL.txt))$/, 1] useful_files << filtered_file if filtered_file.present? useful_files end.sort_by { |file| file.include?('.txt') && 1 || 2 } end def output_path return @path if @path.present? @path = File.join(Dir.pwd, 'public', 'system', 'data', 'imagens', 'landsat8') FileUtils.mkdir_p(@path) @path end def scene_already_proccessed?(file) Scene .landsat8 .by_date(file[:date]) .by_scene(scene.delete('/')) .exists? end def info_object(scene_folder) info_content = IO.read(Dir.glob(File.join(output_path, scene_folder, '*.txt')).first) @info_object = { date: info_content.match(/DATE_ACQUIRED = (.+)/)[1].to_date, cloud_cover: info_content.match(/CLOUD_COVER = (.+)/)[1], scene: info_content.match(/LANDSAT_PRODUCT_ID = (.+)/)[1].split('_').third, source: :landsat8, base_path: output_path, files_path: "#{output_path}/#{scene_folder}" } end def band_object(file) { blue: "#{output_path}/#{file}/#{file}_B2.TIF", green: "#{output_path}/#{file}/#{file}_B3.TIF", red: "#{output_path}/#{file}/#{file}_B4.TIF", near_infrared: "#{output_path}/#{file}/#{file}_B5.TIF", small_thumb: "#{output_path}/#{file}/#{file}_thumb_small.jpg", large_thumb: "#{output_path}/#{file}/#{file}_thumb_large.jpg", info: info_object(file) } if File.exist?(File.join(output_path, file)) end end end end