Updated fetcher and added .vscode folder to gitignore
This commit is contained in:
parent
756270cd1b
commit
830a7eb469
6 changed files with 1213 additions and 1178 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
.vscode
|
||||||
|
|
@ -10,12 +10,18 @@ from sortedcontainers import SortedDict
|
||||||
import tqdm
|
import tqdm
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
path_to_images = r"..\composite\goes18"
|
years = [2024]
|
||||||
output_file = r"..\goes18_2023.mp4"
|
sources = ["goes16", "goes18"]
|
||||||
interp_file = r"..\goes18_2023_interp.mp4"
|
|
||||||
ffmpeg_path = r"..\ffmpeg.exe"
|
ffmpeg_path = r"..\ffmpeg.exe"
|
||||||
starttime = calendar.timegm(datetime.datetime(2023, 1, 1, tzinfo=datetime.timezone.utc).timetuple())
|
|
||||||
stoptime = calendar.timegm(datetime.datetime(2024, 1, 1, tzinfo=datetime.timezone.utc).timetuple())
|
for year in years:
|
||||||
|
for source in sources:
|
||||||
|
path_to_images = f"..\\composite\\{source}"
|
||||||
|
output_file = f"..\\{source}_{year}_nofilt.mp4"
|
||||||
|
interp_file = f"..\\{source}_{year}_interp_nofilt.mp4"
|
||||||
|
|
||||||
|
starttime = calendar.timegm(datetime.datetime(year, 1, 1, tzinfo=datetime.timezone.utc).timetuple())
|
||||||
|
stoptime = calendar.timegm(datetime.datetime(year+1, 1, 1, tzinfo=datetime.timezone.utc).timetuple())
|
||||||
min_file_size = 350000 # Detect and remove corrupted files by filtering by file size
|
min_file_size = 350000 # Detect and remove corrupted files by filtering by file size
|
||||||
max_file_size = 450000
|
max_file_size = 450000
|
||||||
encoding_crf = 16
|
encoding_crf = 16
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ avg_radius = (valid_radii[0] + valid_radii[1]) // 2
|
||||||
max_radius_error = 80
|
max_radius_error = 80
|
||||||
|
|
||||||
ratio_above_thresh_max = 0.4
|
ratio_above_thresh_max = 0.4
|
||||||
ratio_above_thresh_min = 0.1
|
ratio_above_thresh_min = 0.07
|
||||||
|
|
||||||
def filter_fits(work_queue):
|
def filter_fits(work_queue):
|
||||||
lowpriority()
|
lowpriority()
|
||||||
|
|
@ -211,7 +211,7 @@ if __name__ == "__main__":
|
||||||
starttime = calendar.timegm(datetime.datetime(2024, 1, 1, tzinfo=datetime.timezone.utc).timetuple())
|
starttime = calendar.timegm(datetime.datetime(2024, 1, 1, tzinfo=datetime.timezone.utc).timetuple())
|
||||||
stoptime = calendar.timegm(datetime.datetime(2025, 1, 1, tzinfo=datetime.timezone.utc).timetuple())
|
stoptime = calendar.timegm(datetime.datetime(2025, 1, 1, tzinfo=datetime.timezone.utc).timetuple())
|
||||||
|
|
||||||
reprocess_errors = False
|
reprocess_errors = True
|
||||||
nworkers = 16
|
nworkers = 16
|
||||||
|
|
||||||
regex_filename = r"dr_suvi-l2-ci\d{3}_g(16|18)_s\S*\.fits$"
|
regex_filename = r"dr_suvi-l2-ci\d{3}_g(16|18)_s\S*\.fits$"
|
||||||
|
|
|
||||||
|
|
@ -439,9 +439,14 @@ if __name__ == "__main__":
|
||||||
stoptime = calendar.timegm(datetime.datetime(2025, 1, 1, tzinfo=datetime.timezone.utc).timetuple())
|
stoptime = calendar.timegm(datetime.datetime(2025, 1, 1, tzinfo=datetime.timezone.utc).timetuple())
|
||||||
|
|
||||||
regex_filename = r"dr_suvi-l2-ci\d{3}_g(16|18)_s\S*\_f.fits$"
|
regex_filename = r"dr_suvi-l2-ci\d{3}_g(16|18)_s\S*\_f.fits$"
|
||||||
|
|
||||||
nworkers = 16
|
nworkers = 16
|
||||||
max_time_gap = 3
|
max_time_gap = 3
|
||||||
fill_missing_data = True
|
fill_missing_data = False
|
||||||
|
ignore_errors = True
|
||||||
|
|
||||||
|
if ignore_errors:
|
||||||
|
regex_filename = r"dr_suvi-l2-ci\d{3}_g(16|18)_s\S*.fits$"
|
||||||
|
|
||||||
file_prefixes = ["dr_suvi-l2-ci" + n[:-1] for n in image_names]
|
file_prefixes = ["dr_suvi-l2-ci" + n[:-1] for n in image_names]
|
||||||
|
|
||||||
|
|
@ -556,7 +561,7 @@ if __name__ == "__main__":
|
||||||
else: # We have a complete file set, update the last_good_files
|
else: # We have a complete file set, update the last_good_files
|
||||||
last_good_files = files_this_timestamp
|
last_good_files = files_this_timestamp
|
||||||
last_good_file_times = [timestamp for _ in last_good_files]
|
last_good_file_times = [timestamp for _ in last_good_files]
|
||||||
work_queue.put((files_this_timestamp, timestamp, processed_images_dir, False))
|
work_queue.put((files_this_timestamp, timestamp, processed_images_dir, ignore_errors))
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("Finishing current jobs and exiting")
|
print("Finishing current jobs and exiting")
|
||||||
|
|
|
||||||
|
|
@ -15,14 +15,14 @@ from queue import Empty
|
||||||
import tqdm
|
import tqdm
|
||||||
|
|
||||||
directory_url = r"https://data.ngdc.noaa.gov/platforms/solar-space-observing-satellites/goes/"
|
directory_url = r"https://data.ngdc.noaa.gov/platforms/solar-space-observing-satellites/goes/"
|
||||||
stored_images_dir = r"..\Data"
|
stored_images_dir = os.path.abspath(os.path.join("..", "Data"))
|
||||||
# directory_url = r"https://data.ngdc.noaa.gov/platforms/solar-space-observing-satellites/goes/goes16/l2/data/ephe-l2-orb1m/2017/12/"
|
# directory_url = r"https://data.ngdc.noaa.gov/platforms/solar-space-observing-satellites/goes/goes16/l2/data/ephe-l2-orb1m/2017/12/"
|
||||||
# stored_images_dir = r"Z:\NOAA GOES Data\Data\goes16/l2/data/ephe-l2-orb1m/2017/12/"
|
# stored_images_dir = r"Z:\NOAA GOES Data\Data\goes16/l2/data/ephe-l2-orb1m/2017/12/"
|
||||||
ignore_folder_names = ["l1b", "goes17", "2017", "2018", "2019", "2020", "2021", "2022", "2023"]
|
ignore_folder_names = ["Parent Directory", "l1b", "goes17", "2017", "2018", "2019", "2020", "2021", "2022", "2023"]
|
||||||
file_database_path = r"..\file_database.json"
|
file_database_path = os.path.abspath(os.path.join("..", "file_database.json"))
|
||||||
fetch_interval = 0 # 60*60
|
fetch_interval = 0 # 60*60
|
||||||
nfetchworkers = 10 # Be nice to the servers, this value is how many threads will be asking for links and file info at the same time
|
nfetchworkers = 2 # Be nice to the servers, this value is how many threads will be asking for links and file info at the same time
|
||||||
ndownloadworkers = 4 # Be nice to the servers, this value is how many threads will be downloading files at the same time
|
ndownloadworkers = 3 # Be nice to the servers, this value is how many threads will be downloading files at the same time
|
||||||
randomize_order = False
|
randomize_order = False
|
||||||
|
|
||||||
links_regex_pattern = r'(?<=<a href=")([^ ?:]*)(?=">.*\d{4}-\d{2}-\d{2} \d{2}:\d{2})' # Find href links that do not contain question marks or whitespace
|
links_regex_pattern = r'(?<=<a href=")([^ ?:]*)(?=">.*\d{4}-\d{2}-\d{2} \d{2}:\d{2})' # Find href links that do not contain question marks or whitespace
|
||||||
|
|
@ -47,13 +47,15 @@ def find_links_worker(query_work_queue, query_result_queue, attempt_count = 3, r
|
||||||
html_content = response.read().decode('utf-8')
|
html_content = response.read().decode('utf-8')
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Exception while fetching links: {e}")
|
tqdm.tqdm.write(f"Exception while fetching links: {e}")
|
||||||
time.sleep(1 + random.random())
|
time.sleep(1 + random.random())
|
||||||
attempts += 1
|
attempts += 1
|
||||||
if (attempt_count > 1) and (attempts == attempt_count):
|
if (attempt_count > 1) and (attempts == attempt_count):
|
||||||
print(f'\nAfter {attempt_count} retries, could not fetch: {url}')
|
tqdm.tqdm.write(f'\nAfter {attempt_count} retries, could not fetch: {url}')
|
||||||
return
|
|
||||||
|
|
||||||
|
if html_content is None: # We failed to fetch the link for some reason, continue to the next job
|
||||||
|
continue
|
||||||
|
else:
|
||||||
links = links_matcher.findall(html_content)
|
links = links_matcher.findall(html_content)
|
||||||
times = times_matcher.findall(html_content)
|
times = times_matcher.findall(html_content)
|
||||||
sizes = sizes_matcher.findall(html_content)
|
sizes = sizes_matcher.findall(html_content)
|
||||||
|
|
@ -90,8 +92,10 @@ def find_links_worker(query_work_queue, query_result_queue, attempt_count = 3, r
|
||||||
if _link.split(r"/")[-2] in ignore_folder_names:
|
if _link.split(r"/")[-2] in ignore_folder_names:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
|
# print(f"Queueing folder: {urllib.parse.urljoin(url,_link)}")
|
||||||
query_work_queue.put(urllib.parse.urljoin(url,_link))
|
query_work_queue.put(urllib.parse.urljoin(url,_link))
|
||||||
else:
|
else:
|
||||||
|
# print(f"Queueing file: {urllib.parse.urljoin(url,_link)}")
|
||||||
query_result_queue.put((urllib.parse.urljoin(url,_link), _time, _size))
|
query_result_queue.put((urllib.parse.urljoin(url,_link), _time, _size))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -103,11 +107,15 @@ def file_download_worker(download_work_queue, download_result_queue, attempt_cou
|
||||||
return
|
return
|
||||||
url, path, t, s = job
|
url, path, t, s = job
|
||||||
|
|
||||||
|
# print(f"Next job: {url}, {path}, {t}, {s}")
|
||||||
attempts = 0
|
attempts = 0
|
||||||
while attempts < attempt_count:
|
while attempts < attempt_count:
|
||||||
try:
|
try:
|
||||||
|
starttime = time.time()
|
||||||
req = urllib.request.Request(url, data=None)
|
req = urllib.request.Request(url, data=None)
|
||||||
image_data = urllib.request.urlopen(req).read()
|
image_data = urllib.request.urlopen(req, timeout=10.0).read()
|
||||||
|
endtime = time.time()
|
||||||
|
tqdm.tqdm.write(f"Downloaded {url} in {endtime-starttime:0.2f} s | {len(image_data)/1024/1024/(endtime-starttime):0.2f} MB/s")
|
||||||
if math.isclose(len(image_data), s, rel_tol=0.05):
|
if math.isclose(len(image_data), s, rel_tol=0.05):
|
||||||
os.makedirs(os.path.split(path)[0], exist_ok=True)
|
os.makedirs(os.path.split(path)[0], exist_ok=True)
|
||||||
open(path, 'wb').write(image_data)
|
open(path, 'wb').write(image_data)
|
||||||
|
|
@ -118,12 +126,13 @@ def file_download_worker(download_work_queue, download_result_queue, attempt_cou
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if hasattr(e, "code") and e.code == 404: # This is expected if the file has been removed from the site (at least for swpc.noaa.gov)
|
if hasattr(e, "code") and e.code == 404: # This is expected if the file has been removed from the site (at least for swpc.noaa.gov)
|
||||||
attempts += attempt_count
|
attempts += attempt_count
|
||||||
elif attempts == 0:
|
elif (0 < attempts) and (attempts < attempt_count):
|
||||||
print(f"\nA problem occurred on image: {url} | {e}")
|
# tqdm.tqdm.write(f"\nA problem occurred on file: {url} | {e}")
|
||||||
time.sleep(1 + random.random())
|
time.sleep(1 + random.random())
|
||||||
attempts += 1
|
attempts += 1
|
||||||
if (attempt_count > 1) and (attempts == attempt_count):
|
if (attempt_count > 1) and (attempts == attempt_count):
|
||||||
print(f'\nAfter {attempt_count} retries, could not fetch: {url}')
|
tqdm.tqdm.write(f'\nAfter {attempt_count} retries, could not fetch: {url}')
|
||||||
|
tqdm.tqdm.write(f"Exception: {e}")
|
||||||
download_result_queue.put((False, url, t))
|
download_result_queue.put((False, url, t))
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
@ -141,8 +150,8 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
query_work_queue = queue.Queue()
|
query_work_queue = queue.Queue()
|
||||||
query_result_queue = queue.Queue()
|
query_result_queue = queue.Queue()
|
||||||
download_work_queue = queue.Queue()
|
download_work_queue = queue.Queue(maxsize=ndownloadworkers)
|
||||||
download_result_queue = queue.Queue()
|
download_result_queue = queue.Queue(maxsize=ndownloadworkers)
|
||||||
workers = []
|
workers = []
|
||||||
for _ in range(nfetchworkers):
|
for _ in range(nfetchworkers):
|
||||||
t = Thread(target=find_links_worker, args=(query_work_queue, query_result_queue, 3, randomize_order), daemon=True)
|
t = Thread(target=find_links_worker, args=(query_work_queue, query_result_queue, 3, randomize_order), daemon=True)
|
||||||
|
|
@ -203,7 +212,7 @@ if __name__ == "__main__":
|
||||||
already_had_image_count += 1
|
already_had_image_count += 1
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
print(f'Found a mismatched size on file: {filepath} Redownloading!')
|
tqdm.tqdm.write(f'Found a mismatched size on file: {filepath} Redownloading!')
|
||||||
download_work_queue.put((l, filepath, t, s))
|
download_work_queue.put((l, filepath, t, s))
|
||||||
else:
|
else:
|
||||||
# We have a download record, confirm the file actually exists on disk
|
# We have a download record, confirm the file actually exists on disk
|
||||||
|
|
@ -236,23 +245,29 @@ if __name__ == "__main__":
|
||||||
print(f"Unhandled Exception during run: {e}")
|
print(f"Unhandled Exception during run: {e}")
|
||||||
print("Shutting down")
|
print("Shutting down")
|
||||||
|
|
||||||
with open(file_database_path, 'w') as f:
|
|
||||||
f.write(json.dumps(file_info_cache))
|
|
||||||
|
|
||||||
for _ in range(nfetchworkers):
|
for _ in range(nfetchworkers):
|
||||||
try:
|
try:
|
||||||
query_work_queue.put(None, timeout=5.0)
|
query_work_queue.put(None)
|
||||||
except:
|
except:
|
||||||
break
|
break
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
print(f"Downloaded {fetched_image_count} | Already had {already_had_image_count} | Failed {failed_image_count}")
|
print(f"Downloaded {fetched_image_count} | Already had {already_had_image_count} | Failed {failed_image_count}")
|
||||||
|
|
||||||
|
while len(download_work_queue.queue) > 0:
|
||||||
|
print(f"Waiting for {len(download_work_queue.queue)} downloads in queue...")
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
for _ in range(ndownloadworkers):
|
for _ in range(ndownloadworkers):
|
||||||
try:
|
try:
|
||||||
download_work_queue.put(None, timeout=5.0)
|
download_work_queue.put(None, timeout=5.0)
|
||||||
except:
|
except:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
with open(file_database_path, 'w') as f:
|
||||||
|
f.write(json.dumps(file_info_cache))
|
||||||
|
|
||||||
|
print("Waiting for workers to shutdown...")
|
||||||
|
|
||||||
for w in workers:
|
for w in workers:
|
||||||
w.join(5.0)
|
w.join(5.0)
|
||||||
8
requirements.txt
Normal file
8
requirements.txt
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
astropy
|
||||||
|
scikit-image
|
||||||
|
tqdm
|
||||||
|
numpy
|
||||||
|
opencv-python
|
||||||
|
palettable
|
||||||
|
matplotlib
|
||||||
|
pillow
|
||||||
Loading…
Add table
Reference in a new issue