Class: Satellite::Sentinel2::ImageryService

Inherits:
Object
  • Object
show all
Defined in:
lib/satellite/sentinel2/imagery_service.rb

Constant Summary collapse

AWS_URL =

Informações sobre –region eu-central-1 –request-payer requester:

https://forum.sentinel-hub.com/t/changes-of-the-access-rights-to-l1c-bucket-at-aws-public-datasets-requester-pays/172
'--region eu-central-1 --request-payer requester s3://sentinel-s2-l1c/tiles'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scene, quantity = 2) ⇒ ImageryService

$scene = ‘12ABC’ String(5)



19
20
21
22
# File 'lib/satellite/sentinel2/imagery_service.rb', line 19

def initialize(scene, quantity = 2)
  self.scene = "#{scene[0..1]}/#{scene[2]}/#{scene[3..4]}"
  self.quantity = quantity
end

Instance Attribute Details

#quantityObject

Returns the value of attribute quantity.



16
17
18
# File 'lib/satellite/sentinel2/imagery_service.rb', line 16

def quantity
  @quantity
end

#sceneObject

Returns the value of attribute scene.



16
17
18
# File 'lib/satellite/sentinel2/imagery_service.rb', line 16

def scene
  @scene
end

Instance Method Details

#band_object(scene_date) ⇒ Object



132
133
134
135
136
137
138
139
140
141
# File 'lib/satellite/sentinel2/imagery_service.rb', line 132

def band_object(scene_date)
  {
    blue:               "#{output_path}/#{scene}/#{scene_date}/B02.jp2",
    green:              "#{output_path}/#{scene}/#{scene_date}/B03.jp2",
    red:                "#{output_path}/#{scene}/#{scene_date}/B04.jp2",
    near_infrared:      "#{output_path}/#{scene}/#{scene_date}/B08.jp2",
    large_thumb:        "#{output_path}/#{scene}/#{scene_date}/preview.jpg",
    info:               info_object(scene_date)
  }
end

#download_and_proccessObject



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/satellite/sentinel2/imagery_service.rb', line 24

def download_and_proccess
  Rails.logger.info "[Sentinel2 | #{scene}] Listando últimos #{quantity} arquivos..."
  files = last_scene_dates

  Rails.logger.info "[Sentinel2 | #{scene}] Checando arquivos que precisam ser baixados..."
  files.reject!{ |scene_date| scene_already_proccessed?(scene_date) }

  Rails.logger.info "[Sentinel2 | #{scene}] Baixando #{files.length} cenas..."
  files.each_with_index do |scene_date, index|
    Rails.logger.info "[Sentinel2 | #{scene}] Fazendo download da cena do dia #{scene_date}..."
    useful_files(scene_date).map do |useful_file|
      Thread.new {
        Rails.logger.info "[Sentinel2 | #{scene}] Fazendo download do arquivo #{useful_file}..."
        `aws s3 cp #{AWS_URL}/#{scene}/#{scene_date}/0/#{useful_file} "#{output_path}/#{scene}/#{scene_date}/#{useful_file}"`
        raise 'Error to execute aws s3 cp' unless $?.success?
      }
    end.map(&:join)

    Rails.logger.info "[Sentinel2 | #{scene}] Processando arquivos #{index.next}/#{files.length}."
    Satellite::ImageryProccessor.new(band_object(scene_date)).proccess
  end
end

#info_object(scene_date) ⇒ Object



121
122
123
124
125
126
127
128
129
130
# File 'lib/satellite/sentinel2/imagery_service.rb', line 121

def info_object(scene_date)
  {
    date: scene_date.to_date,
    cloud_cover: nil,
    scene: scene.delete('/'),
    source: :sentinel2,
    base_path: output_path,
    files_path: "#{output_path}/#{scene}/#{scene_date}"
  }
end

#last_scene_datesObject



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/satellite/sentinel2/imagery_service.rb', line 47

def last_scene_dates
  return @last_scene_dates if @last_scene_dates.present?

  @last_scene_dates = []

  scene_years.sort.reverse.each do |year|
    break if @last_scene_dates.size == quantity
    scene_months(year).sort.reverse.each do |month|
      break if @last_scene_dates.size == quantity
      scene_days(year, month).sort.reverse.each do |day|
        break if @last_scene_dates.size == quantity
        @last_scene_dates << "#{year}/#{month}/#{day}"
      end
    end
  end

  @last_scene_dates
end

#output_pathObject



105
106
107
108
109
110
111
# File 'lib/satellite/sentinel2/imagery_service.rb', line 105

def output_path
  return @path if @path.present?

  @path = File.join(Dir.pwd, 'public', 'system', 'data', 'imagens', 'sentinel2')
  FileUtils.mkdir_p(@path)
  @path
end

#scene_already_proccessed?(scene_date) ⇒ Boolean

Returns:

  • (Boolean)


113
114
115
116
117
118
119
# File 'lib/satellite/sentinel2/imagery_service.rb', line 113

def scene_already_proccessed?(scene_date)
  Scene
    .sentinel2
    .by_date(scene_date.to_date)
    .by_scene(scene.delete('/'))
    .exists?
end

#scene_days(year, month) ⇒ Object



85
86
87
88
89
90
# File 'lib/satellite/sentinel2/imagery_service.rb', line 85

def scene_days(year, month)
  days_list = `aws s3 ls #{AWS_URL}/#{scene}/#{year}/#{month}/`
  raise 'Falha ao executar comando para adquirir o dia da última cena' unless $?.success?

  days_list.split("\n").map(&string_as_integer)
end

#scene_months(year) ⇒ Object



78
79
80
81
82
83
# File 'lib/satellite/sentinel2/imagery_service.rb', line 78

def scene_months(year)
  months_list = `aws s3 ls #{AWS_URL}/#{scene}/#{year}/`
  raise 'Falha ao executar comando para adquirir o mês da última cena' unless $?.success?

  months_list.split("\n").map(&string_as_integer)
end

#scene_yearsObject



70
71
72
73
74
75
76
# File 'lib/satellite/sentinel2/imagery_service.rb', line 70

def scene_years
  return @scene_years if @scene_years.present?

  years_list = `aws s3 ls #{AWS_URL}/#{scene}/`
  raise 'Falha ao executar comando para adquirir os anos da cena' unless $?.success?
  @scene_years = years_list.split("\n").map(&string_as_integer)
end

#string_as_integerObject



66
67
68
# File 'lib/satellite/sentinel2/imagery_service.rb', line 66

def string_as_integer
  ->(string) { string[/(\d+)/, 1].to_i }
end

#useful_files(scene_date) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/satellite/sentinel2/imagery_service.rb', line 92

def useful_files(scene_date)
  # O parâmetro 0 no fim da string é por que caso o satélite tire mais de uma foto no mesmo dia
  # estas serão armazenadas em /1, /2, etc... porém isso só ocorre em latitudes do norte.
  all_files_from_last_scene = `aws s3 ls #{AWS_URL}/#{scene}/#{scene_date}/0/`
  raise 'Falha ao executar comando para adquirir a lista de arquivos' unless $?.success?

  @useful_files = all_files_from_last_scene.split("\n").inject([]) do |useful_files, current_file|
    filtered_file = current_file[/.*(B0[2-4].jp2|B08.jp2|preview.jpg)$/, 1]
    useful_files << filtered_file if filtered_file.present?
    useful_files
  end
end