├── LICENSE ├── README.md ├── aia_fits_to_zarr.py ├── eve_npy_to_zarr.py ├── hmi_fits_to_zarr.py └── save_filelists.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 SDO Machine Learning Dataset 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SDOMLv2 2 | 3 | This gitlab repository contains python scripts for getting and processing SDO/AIA, SDO/HMI, and SDO/EVE files to new cloud-friendly .zarr files (SDOMLv2). The data is essentially the same as previous SDOML. For more details about the SDOML dataset, please refer to the following paper: 4 | 5 | "A Machine-learning Data Set Prepared from the NASA Solar Dynamics Observatory Mission" http://adsabs.harvard.edu/abs/2019ApJS..242....7G 6 | 7 | The major changes in SDOMLv2 include: 8 | 9 | - Using the cloud-friendly Zarr format for the storage of chunked, compressed, N-dimensional arrays (https://zarr.readthedocs.io/en/stable/). 10 | - All fits header information is saved in the meta data. 11 | 12 | A brief description about each script: 13 | * aia_fits_to_zarr.py for processing the AIA synoptic fits data to zarr files 14 | * hmi_fits_to_zarr.py for processing the HMI fits data to zarr files 15 | * eve_npy_to_zarr.py for processing the EVE npy files (from SDOMLv1) to zarr files 16 | * save_filelists.py for saving file lists of AIA channels 17 | -------------------------------------------------------------------------------- /aia_fits_to_zarr.py: -------------------------------------------------------------------------------- 1 | #Given: 2 | # a folder --target to contain zarr files 3 | # an integer --scale (a proper divisor of 1024) containing the target output size 4 | #Converts the source fits files to target zarr files: 5 | # -Rescaling the sun to a constant pixel size and correcting for invalid interpolation 6 | # -Applying the degradation constant and accounting for exposure time 7 | # -Then downsampling by mean 8 | # -Save all fits header information to meta data in zarr 9 | 10 | import os, pdb 11 | import numpy as np 12 | import sunpy.io 13 | from tqdm import tqdm 14 | import zarr 15 | from sunpy.map import Map 16 | import skimage.transform 17 | import gcsfs 18 | from numcodecs import Blosc, Delta 19 | import warnings 20 | import argparse 21 | 22 | warnings.filterwarnings("ignore") 23 | 24 | CHANNELS = [131,1600,1700,171,193,211,304,335,94,4500] 25 | trgtAS = 976.0 26 | 27 | def parse_args(): 28 | parser = argparse.ArgumentParser() 29 | parser.add_argument('--target',dest='target',required=True) 30 | parser.add_argument('--scale',dest='scale',required=True,type=int) 31 | args = parser.parse_args() 32 | return args 33 | 34 | def loadAIADegrads(path): 35 | #return wavelength -> (date -> degradation dictionary) 36 | degrads = {} 37 | for wl in CHANNELS: 38 | degrads[wl] = getDegrad("%s/degrad_%d.csv" % (path,wl)) 39 | return degrads 40 | 41 | def getDegrad(fn): 42 | #map YYYY-MM-DD -> degradation parameter 43 | lines = open(fn).read().strip().split("\n") 44 | degrad = {} 45 | for l in lines: 46 | d, f = l.split(",") 47 | degrad[d[1:11]] = float(f) 48 | return degrad 49 | 50 | if __name__ == "__main__": 51 | args = parse_args() 52 | 53 | degrads = loadAIADegrads("degrad/") 54 | print(np.shape(degrads)) 55 | 56 | print(args) 57 | target, scale = args.target, args.scale 58 | 59 | if not os.path.exists(target): 60 | os.mkdir(target) 61 | 62 | divideFactor = np.int(1024 / scale) 63 | 64 | #load file lists for AIA channels 65 | filelist_131 = np.load('./filelists_2011/filelist_131.npy') 66 | filelist_1600 = np.load('./filelists_2011/filelist_1600.npy') 67 | filelist_1700 = np.load('./filelists_2011/filelist_1700.npy') 68 | filelist_171 = np.load('./filelists_2011/filelist_171.npy') 69 | filelist_193 = np.load('./filelists_2011/filelist_193.npy') 70 | filelist_211 = np.load('./filelists_2011/filelist_211.npy') 71 | filelist_304 = np.load('./filelists_2011/filelist_304.npy') 72 | filelist_335 = np.load('./filelists_2011/filelist_335.npy') 73 | filelist_94 = np.load('./filelists_2011/filelist_94.npy') 74 | 75 | store = zarr.DirectoryStore(target+'sdomlv2_2011.zarr') 76 | compressor = Blosc(cname='zstd', clevel=5, shuffle=Blosc.BITSHUFFLE) 77 | root = zarr.group(store=store,overwrite=True) 78 | year = root.create_group('2011') 79 | aia131 = year.create_dataset('131A',shape=(np.shape(filelist_131)[0],scale,scale),chunks=(15,None,None),dtype='f4',compressor=compressor) 80 | aia1600 = year.create_dataset('1600A',shape=(np.shape(filelist_1600)[0],scale,scale),chunks=(15,None,None),dtype='f4',compressor=compressor) 81 | aia1700 = year.create_dataset('1700A',shape=(np.shape(filelist_1700)[0],scale,scale),chunks=(15,None,None),dtype='f4',compressor=compressor) 82 | aia171 = year.create_dataset('171A',shape=(np.shape(filelist_171)[0],scale,scale),chunks=(15,None,None),dtype='f4',compressor=compressor) 83 | aia193 = year.create_dataset('193A',shape=(np.shape(filelist_193)[0],scale,scale),chunks=(15,None,None),dtype='f4',compressor=compressor) 84 | aia211 = year.create_dataset('211A',shape=(np.shape(filelist_211)[0],scale,scale),chunks=(15,None,None),dtype='f4',compressor=compressor) 85 | aia304 = year.create_dataset('304A',shape=(np.shape(filelist_304)[0],scale,scale),chunks=(15,None,None),dtype='f4',compressor=compressor) 86 | aia335 = year.create_dataset('335A',shape=(np.shape(filelist_335)[0],scale,scale),chunks=(15,None,None),dtype='f4',compressor=compressor) 87 | aia94 = year.create_dataset('94A',shape=(np.shape(filelist_94)[0],scale,scale),chunks=(15,None,None),dtype='f4',compressor=compressor) 88 | 89 | # Process 131A 90 | Xd = Map(filelist_131[0]) 91 | for key in Xd.meta: 92 | if key != 'keycomments' and key != 'simple': 93 | vars()[key] = [] 94 | deg_cor = [] 95 | pixlunit = [] 96 | 97 | for fn,file in tqdm(enumerate(filelist_131)): 98 | Xd = Map(file) 99 | fn2 = file[-26:].split("_")[0].replace("AIA","") 100 | datestring = "%s-%s-%s" % (fn2[:4],fn2[4:6],fn2[6:8]) 101 | wavelength = int(file[-26:].split("_")[-1].replace(".fits","")) 102 | correction = degrads[wavelength][datestring] 103 | 104 | for key in Xd.meta: 105 | if key != 'keycomments' and key != 'simple': 106 | vars()[key].append(Xd.meta[key]) 107 | deg_cor.append(correction) 108 | pixlunit.append('DN/s') 109 | 110 | X = Xd.data 111 | validMask = 1.0 * (X > 0) 112 | X[np.where(X<=0.0)] = 0.0 113 | expTime = max(Xd.meta['EXPTIME'],1e-2) 114 | rad = Xd.meta['RSUN_OBS'] 115 | scale_factor = trgtAS/rad 116 | t = (X.shape[0]/2.0)-scale_factor*(X.shape[0]/2.0) 117 | XForm = skimage.transform.SimilarityTransform(scale=scale_factor,translation=(t,t)) 118 | Xr = skimage.transform.warp(X,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 119 | Xm = skimage.transform.warp(validMask,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 120 | Xr = np.divide(Xr,(Xm+1e-8)) 121 | Xr = Xr / (expTime*correction) 122 | Xr = skimage.transform.downscale_local_mean(Xr,(divideFactor,divideFactor)) 123 | Xr = Xr.astype('float32') 124 | aia131[fn,:,:]=Xr 125 | 126 | for key in Xd.meta: 127 | if key != 'keycomments' and key != 'simple': 128 | aia131.attrs[key.upper()]=vars()[key] 129 | 130 | aia131.attrs['NAXIS1'] = list(np.asarray(naxis1, dtype=np.float64) / divideFactor) 131 | aia131.attrs['NAXIS2'] = list(np.asarray(naxis2, dtype=np.float64) / divideFactor) 132 | aia131.attrs['CDELT1'] = list(np.asarray(cdelt1, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 133 | aia131.attrs['CDELT2'] = list(np.asarray(cdelt2, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 134 | aia131.attrs['R_SUN'] = list(np.asarray(r_sun, dtype=np.float64) / (4. * divideFactor) * trgtAS / rsun_obs) 135 | aia131.attrs['X0_MP'] = list(np.asarray(x0_mp, dtype=np.float64) / (4. * divideFactor)) 136 | aia131.attrs['Y0_MP'] = list(np.asarray(y0_mp, dtype=np.float64) / (4. * divideFactor)) 137 | aia131.attrs['CRPIX1'] = list(np.asarray(crpix1, dtype=np.float64) / divideFactor) 138 | aia131.attrs['CRPIX2'] = list(np.asarray(crpix2, dtype=np.float64) / divideFactor) 139 | aia131.attrs['DEG_COR'] = list(np.asarray(deg_cor, dtype=np.float64)) 140 | aia131.attrs['PIXLUNIT'] = list(pixlunit) 141 | 142 | # Process 1600A 143 | Xd = Map(filelist_1600[0]) 144 | for key in Xd.meta: 145 | if key != 'keycomments' and key != 'simple': 146 | vars()[key] = [] 147 | deg_cor = [] 148 | pixlunit = [] 149 | 150 | for fn,file in tqdm(enumerate(filelist_1600)): 151 | Xd = Map(file) 152 | fn2 = file[-26:].split("_")[0].replace("AIA","") 153 | datestring = "%s-%s-%s" % (fn2[:4],fn2[4:6],fn2[6:8]) 154 | wavelength = int(file[-26:].split("_")[-1].replace(".fits","")) 155 | correction = degrads[wavelength][datestring] 156 | 157 | for key in Xd.meta: 158 | if key != 'keycomments' and key != 'simple': 159 | vars()[key].append(Xd.meta[key]) 160 | deg_cor.append(correction) 161 | pixlunit.append('DN/s') 162 | 163 | X = Xd.data 164 | validMask = 1.0 * (X > 0) 165 | X[np.where(X<=0.0)] = 0.0 166 | expTime = max(Xd.meta['EXPTIME'],1e-2) 167 | rad = Xd.meta['RSUN_OBS'] 168 | scale_factor = trgtAS/rad 169 | t = (X.shape[0]/2.0)-scale_factor*(X.shape[0]/2.0) 170 | XForm = skimage.transform.SimilarityTransform(scale=scale_factor,translation=(t,t)) 171 | Xr = skimage.transform.warp(X,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 172 | Xm = skimage.transform.warp(validMask,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 173 | Xr = np.divide(Xr,(Xm+1e-8)) 174 | Xr = Xr / (expTime*correction) 175 | Xr = skimage.transform.downscale_local_mean(Xr,(divideFactor,divideFactor)) 176 | Xr = Xr.astype('float32') 177 | aia1600[fn,:,:]=Xr 178 | 179 | for key in Xd.meta: 180 | if key != 'keycomments' and key != 'simple': 181 | aia1600.attrs[key.upper()]=vars()[key] 182 | 183 | aia1600.attrs['NAXIS1'] = list(np.asarray(naxis1, dtype=np.float64) / divideFactor) 184 | aia1600.attrs['NAXIS2'] = list(np.asarray(naxis2, dtype=np.float64) / divideFactor) 185 | aia1600.attrs['CDELT1'] = list(np.asarray(cdelt1, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 186 | aia1600.attrs['CDELT2'] = list(np.asarray(cdelt2, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 187 | aia1600.attrs['R_SUN'] = list(np.asarray(r_sun, dtype=np.float64) / (4. * divideFactor) * trgtAS / rsun_obs) 188 | aia1600.attrs['X0_MP'] = list(np.asarray(x0_mp, dtype=np.float64) / (4. * divideFactor)) 189 | aia1600.attrs['Y0_MP'] = list(np.asarray(y0_mp, dtype=np.float64) / (4. * divideFactor)) 190 | aia1600.attrs['CRPIX1'] = list(np.asarray(crpix1, dtype=np.float64) / divideFactor) 191 | aia1600.attrs['CRPIX2'] = list(np.asarray(crpix2, dtype=np.float64) / divideFactor) 192 | aia1600.attrs['DEG_COR'] = list(np.asarray(deg_cor, dtype=np.float64)) 193 | aia1600.attrs['PIXLUNIT'] = list(pixlunit) 194 | 195 | # Process 1700A 196 | Xd = Map(filelist_1700[0]) 197 | for key in Xd.meta: 198 | if key != 'keycomments' and key != 'simple': 199 | vars()[key] = [] 200 | deg_cor = [] 201 | pixlunit = [] 202 | 203 | for fn,file in tqdm(enumerate(filelist_1700)): 204 | Xd = Map(file) 205 | fn2 = file[-26:].split("_")[0].replace("AIA","") 206 | datestring = "%s-%s-%s" % (fn2[:4],fn2[4:6],fn2[6:8]) 207 | wavelength = int(file[-26:].split("_")[-1].replace(".fits","")) 208 | correction = degrads[wavelength][datestring] 209 | 210 | for key in Xd.meta: 211 | if key != 'keycomments' and key != 'simple': 212 | vars()[key].append(Xd.meta[key]) 213 | deg_cor.append(correction) 214 | pixlunit.append('DN/s') 215 | 216 | X = Xd.data 217 | validMask = 1.0 * (X > 0) 218 | X[np.where(X<=0.0)] = 0.0 219 | expTime = max(Xd.meta['EXPTIME'],1e-2) 220 | rad = Xd.meta['RSUN_OBS'] 221 | scale_factor = trgtAS/rad 222 | t = (X.shape[0]/2.0)-scale_factor*(X.shape[0]/2.0) 223 | XForm = skimage.transform.SimilarityTransform(scale=scale_factor,translation=(t,t)) 224 | Xr = skimage.transform.warp(X,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 225 | Xm = skimage.transform.warp(validMask,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 226 | Xr = np.divide(Xr,(Xm+1e-8)) 227 | Xr = Xr / (expTime*correction) 228 | Xr = skimage.transform.downscale_local_mean(Xr,(divideFactor,divideFactor)) 229 | Xr = Xr.astype('float32') 230 | aia1700[fn,:,:]=Xr 231 | 232 | for key in Xd.meta: 233 | if key != 'keycomments' and key != 'simple': 234 | aia1700.attrs[key.upper()]=vars()[key] 235 | 236 | aia1700.attrs['NAXIS1'] = list(np.asarray(naxis1, dtype=np.float64) / divideFactor) 237 | aia1700.attrs['NAXIS2'] = list(np.asarray(naxis2, dtype=np.float64) / divideFactor) 238 | aia1700.attrs['CDELT1'] = list(np.asarray(cdelt1, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 239 | aia1700.attrs['CDELT2'] = list(np.asarray(cdelt2, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 240 | aia1700.attrs['R_SUN'] = list(np.asarray(r_sun, dtype=np.float64) / (4. * divideFactor) * trgtAS / rsun_obs) 241 | aia1700.attrs['X0_MP'] = list(np.asarray(x0_mp, dtype=np.float64) / (4. * divideFactor)) 242 | aia1700.attrs['Y0_MP'] = list(np.asarray(y0_mp, dtype=np.float64) / (4. * divideFactor)) 243 | aia1700.attrs['CRPIX1'] = list(np.asarray(crpix1, dtype=np.float64) / divideFactor) 244 | aia1700.attrs['CRPIX2'] = list(np.asarray(crpix2, dtype=np.float64) / divideFactor) 245 | aia1700.attrs['DEG_COR'] = list(np.asarray(deg_cor, dtype=np.float64)) 246 | aia1700.attrs['PIXLUNIT'] = list(pixlunit) 247 | 248 | # Process 171A 249 | Xd = Map(filelist_171[0]) 250 | for key in Xd.meta: 251 | if key != 'keycomments' and key != 'simple': 252 | vars()[key] = [] 253 | deg_cor = [] 254 | pixlunit = [] 255 | 256 | for fn,file in tqdm(enumerate(filelist_171)): 257 | Xd = Map(file) 258 | fn2 = file[-26:].split("_")[0].replace("AIA","") 259 | datestring = "%s-%s-%s" % (fn2[:4],fn2[4:6],fn2[6:8]) 260 | wavelength = int(file[-26:].split("_")[-1].replace(".fits","")) 261 | correction = degrads[wavelength][datestring] 262 | 263 | for key in Xd.meta: 264 | if key != 'keycomments' and key != 'simple': 265 | vars()[key].append(Xd.meta[key]) 266 | deg_cor.append(correction) 267 | pixlunit.append('DN/s') 268 | 269 | X = Xd.data 270 | validMask = 1.0 * (X > 0) 271 | X[np.where(X<=0.0)] = 0.0 272 | expTime = max(Xd.meta['EXPTIME'],1e-2) 273 | rad = Xd.meta['RSUN_OBS'] 274 | scale_factor = trgtAS/rad 275 | t = (X.shape[0]/2.0)-scale_factor*(X.shape[0]/2.0) 276 | XForm = skimage.transform.SimilarityTransform(scale=scale_factor,translation=(t,t)) 277 | Xr = skimage.transform.warp(X,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 278 | Xm = skimage.transform.warp(validMask,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 279 | Xr = np.divide(Xr,(Xm+1e-8)) 280 | Xr = Xr / (expTime*correction) 281 | Xr = skimage.transform.downscale_local_mean(Xr,(divideFactor,divideFactor)) 282 | Xr = Xr.astype('float32') 283 | aia171[fn,:,:]=Xr 284 | 285 | for key in Xd.meta: 286 | if key != 'keycomments' and key != 'simple': 287 | aia171.attrs[key.upper()]=vars()[key] 288 | 289 | aia171.attrs['NAXIS1'] = list(np.asarray(naxis1, dtype=np.float64) / divideFactor) 290 | aia171.attrs['NAXIS2'] = list(np.asarray(naxis2, dtype=np.float64) / divideFactor) 291 | aia171.attrs['CDELT1'] = list(np.asarray(cdelt1, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 292 | aia171.attrs['CDELT2'] = list(np.asarray(cdelt2, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 293 | aia171.attrs['R_SUN'] = list(np.asarray(r_sun, dtype=np.float64) / (4. * divideFactor) * trgtAS / rsun_obs) 294 | aia171.attrs['X0_MP'] = list(np.asarray(x0_mp, dtype=np.float64) / (4. * divideFactor)) 295 | aia171.attrs['Y0_MP'] = list(np.asarray(y0_mp, dtype=np.float64) / (4. * divideFactor)) 296 | aia171.attrs['CRPIX1'] = list(np.asarray(crpix1, dtype=np.float64) / divideFactor) 297 | aia171.attrs['CRPIX2'] = list(np.asarray(crpix2, dtype=np.float64) / divideFactor) 298 | aia171.attrs['DEG_COR'] = list(np.asarray(deg_cor, dtype=np.float64)) 299 | aia171.attrs['PIXLUNIT'] = list(pixlunit) 300 | 301 | # Process 193A 302 | Xd = Map(filelist_193[0]) 303 | for key in Xd.meta: 304 | if key != 'keycomments' and key != 'simple': 305 | vars()[key] = [] 306 | deg_cor = [] 307 | pixlunit = [] 308 | 309 | for fn,file in tqdm(enumerate(filelist_193)): 310 | Xd = Map(file) 311 | fn2 = file[-26:].split("_")[0].replace("AIA","") 312 | datestring = "%s-%s-%s" % (fn2[:4],fn2[4:6],fn2[6:8]) 313 | wavelength = int(file[-26:].split("_")[-1].replace(".fits","")) 314 | correction = degrads[wavelength][datestring] 315 | 316 | for key in Xd.meta: 317 | if key != 'keycomments' and key != 'simple': 318 | vars()[key].append(Xd.meta[key]) 319 | deg_cor.append(correction) 320 | pixlunit.append('DN/s') 321 | 322 | X = Xd.data 323 | validMask = 1.0 * (X > 0) 324 | X[np.where(X<=0.0)] = 0.0 325 | expTime = max(Xd.meta['EXPTIME'],1e-2) 326 | rad = Xd.meta['RSUN_OBS'] 327 | scale_factor = trgtAS/rad 328 | t = (X.shape[0]/2.0)-scale_factor*(X.shape[0]/2.0) 329 | XForm = skimage.transform.SimilarityTransform(scale=scale_factor,translation=(t,t)) 330 | Xr = skimage.transform.warp(X,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 331 | Xm = skimage.transform.warp(validMask,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 332 | Xr = np.divide(Xr,(Xm+1e-8)) 333 | Xr = Xr / (expTime*correction) 334 | Xr = skimage.transform.downscale_local_mean(Xr,(divideFactor,divideFactor)) 335 | Xr = Xr.astype('float32') 336 | aia193[fn,:,:]=Xr 337 | 338 | for key in Xd.meta: 339 | if key != 'keycomments' and key != 'simple': 340 | aia193.attrs[key.upper()]=vars()[key] 341 | 342 | aia193.attrs['NAXIS1'] = list(np.asarray(naxis1, dtype=np.float64) / divideFactor) 343 | aia193.attrs['NAXIS2'] = list(np.asarray(naxis2, dtype=np.float64) / divideFactor) 344 | aia193.attrs['CDELT1'] = list(np.asarray(cdelt1, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 345 | aia193.attrs['CDELT2'] = list(np.asarray(cdelt2, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 346 | aia193.attrs['R_SUN'] = list(np.asarray(r_sun, dtype=np.float64) / (4. * divideFactor) * trgtAS / rsun_obs) 347 | aia193.attrs['X0_MP'] = list(np.asarray(x0_mp, dtype=np.float64) / (4. * divideFactor)) 348 | aia193.attrs['Y0_MP'] = list(np.asarray(y0_mp, dtype=np.float64) / (4. * divideFactor)) 349 | aia193.attrs['CRPIX1'] = list(np.asarray(crpix1, dtype=np.float64) / divideFactor) 350 | aia193.attrs['CRPIX2'] = list(np.asarray(crpix2, dtype=np.float64) / divideFactor) 351 | aia193.attrs['DEG_COR'] = list(np.asarray(deg_cor, dtype=np.float64)) 352 | aia193.attrs['PIXLUNIT'] = list(pixlunit) 353 | 354 | # Process 211A 355 | Xd = Map(filelist_211[0]) 356 | for key in Xd.meta: 357 | if key != 'keycomments' and key != 'simple': 358 | vars()[key] = [] 359 | deg_cor = [] 360 | pixlunit = [] 361 | 362 | for fn,file in tqdm(enumerate(filelist_211)): 363 | Xd = Map(file) 364 | fn2 = file[-26:].split("_")[0].replace("AIA","") 365 | datestring = "%s-%s-%s" % (fn2[:4],fn2[4:6],fn2[6:8]) 366 | wavelength = int(file[-26:].split("_")[-1].replace(".fits","")) 367 | correction = degrads[wavelength][datestring] 368 | 369 | for key in Xd.meta: 370 | if key != 'keycomments' and key != 'simple': 371 | vars()[key].append(Xd.meta[key]) 372 | deg_cor.append(correction) 373 | pixlunit.append('DN/s') 374 | 375 | X = Xd.data 376 | validMask = 1.0 * (X > 0) 377 | X[np.where(X<=0.0)] = 0.0 378 | expTime = max(Xd.meta['EXPTIME'],1e-2) 379 | rad = Xd.meta['RSUN_OBS'] 380 | scale_factor = trgtAS/rad 381 | t = (X.shape[0]/2.0)-scale_factor*(X.shape[0]/2.0) 382 | XForm = skimage.transform.SimilarityTransform(scale=scale_factor,translation=(t,t)) 383 | Xr = skimage.transform.warp(X,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 384 | Xm = skimage.transform.warp(validMask,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 385 | Xr = np.divide(Xr,(Xm+1e-8)) 386 | Xr = Xr / (expTime*correction) 387 | Xr = skimage.transform.downscale_local_mean(Xr,(divideFactor,divideFactor)) 388 | Xr = Xr.astype('float32') 389 | aia211[fn,:,:]=Xr 390 | 391 | for key in Xd.meta: 392 | if key != 'keycomments' and key != 'simple': 393 | aia211.attrs[key.upper()]=vars()[key] 394 | 395 | aia211.attrs['NAXIS1'] = list(np.asarray(naxis1, dtype=np.float64) / divideFactor) 396 | aia211.attrs['NAXIS2'] = list(np.asarray(naxis2, dtype=np.float64) / divideFactor) 397 | aia211.attrs['CDELT1'] = list(np.asarray(cdelt1, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 398 | aia211.attrs['CDELT2'] = list(np.asarray(cdelt2, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 399 | aia211.attrs['R_SUN'] = list(np.asarray(r_sun, dtype=np.float64) / (4. * divideFactor) * trgtAS / rsun_obs) 400 | aia211.attrs['X0_MP'] = list(np.asarray(x0_mp, dtype=np.float64) / (4. * divideFactor)) 401 | aia211.attrs['Y0_MP'] = list(np.asarray(y0_mp, dtype=np.float64) / (4. * divideFactor)) 402 | aia211.attrs['CRPIX1'] = list(np.asarray(crpix1, dtype=np.float64) / divideFactor) 403 | aia211.attrs['CRPIX2'] = list(np.asarray(crpix2, dtype=np.float64) / divideFactor) 404 | aia211.attrs['DEG_COR'] = list(np.asarray(deg_cor, dtype=np.float64)) 405 | aia211.attrs['PIXLUNIT'] = list(pixlunit) 406 | 407 | # Process 304A 408 | Xd = Map(filelist_304[0]) 409 | for key in Xd.meta: 410 | if key != 'keycomments' and key != 'simple': 411 | vars()[key] = [] 412 | deg_cor = [] 413 | pixlunit = [] 414 | 415 | for fn,file in tqdm(enumerate(filelist_304)): 416 | Xd = Map(file) 417 | fn2 = file[-26:].split("_")[0].replace("AIA","") 418 | datestring = "%s-%s-%s" % (fn2[:4],fn2[4:6],fn2[6:8]) 419 | wavelength = int(file[-26:].split("_")[-1].replace(".fits","")) 420 | correction = degrads[wavelength][datestring] 421 | 422 | for key in Xd.meta: 423 | if key != 'keycomments' and key != 'simple': 424 | vars()[key].append(Xd.meta[key]) 425 | deg_cor.append(correction) 426 | pixlunit.append('DN/s') 427 | 428 | X = Xd.data 429 | validMask = 1.0 * (X > 0) 430 | X[np.where(X<=0.0)] = 0.0 431 | expTime = max(Xd.meta['EXPTIME'],1e-2) 432 | rad = Xd.meta['RSUN_OBS'] 433 | scale_factor = trgtAS/rad 434 | t = (X.shape[0]/2.0)-scale_factor*(X.shape[0]/2.0) 435 | XForm = skimage.transform.SimilarityTransform(scale=scale_factor,translation=(t,t)) 436 | Xr = skimage.transform.warp(X,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 437 | Xm = skimage.transform.warp(validMask,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 438 | Xr = np.divide(Xr,(Xm+1e-8)) 439 | Xr = Xr / (expTime*correction) 440 | Xr = skimage.transform.downscale_local_mean(Xr,(divideFactor,divideFactor)) 441 | Xr = Xr.astype('float32') 442 | aia304[fn,:,:]=Xr 443 | 444 | for key in Xd.meta: 445 | if key != 'keycomments' and key != 'simple': 446 | aia304.attrs[key.upper()]=vars()[key] 447 | 448 | aia304.attrs['NAXIS1'] = list(np.asarray(naxis1, dtype=np.float64) / divideFactor) 449 | aia304.attrs['NAXIS2'] = list(np.asarray(naxis2, dtype=np.float64) / divideFactor) 450 | aia304.attrs['CDELT1'] = list(np.asarray(cdelt1, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 451 | aia304.attrs['CDELT2'] = list(np.asarray(cdelt2, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 452 | aia304.attrs['R_SUN'] = list(np.asarray(r_sun, dtype=np.float64) / (4. * divideFactor) * trgtAS / rsun_obs) 453 | aia304.attrs['X0_MP'] = list(np.asarray(x0_mp, dtype=np.float64) / (4. * divideFactor)) 454 | aia304.attrs['Y0_MP'] = list(np.asarray(y0_mp, dtype=np.float64) / (4. * divideFactor)) 455 | aia304.attrs['CRPIX1'] = list(np.asarray(crpix1, dtype=np.float64) / divideFactor) 456 | aia304.attrs['CRPIX2'] = list(np.asarray(crpix2, dtype=np.float64) / divideFactor) 457 | aia304.attrs['DEG_COR'] = list(np.asarray(deg_cor, dtype=np.float64)) 458 | aia304.attrs['PIXLUNIT'] = list(pixlunit) 459 | 460 | # Process 335A 461 | Xd = Map(filelist_335[0]) 462 | for key in Xd.meta: 463 | if key != 'keycomments' and key != 'simple': 464 | vars()[key] = [] 465 | deg_cor = [] 466 | pixlunit = [] 467 | 468 | for fn,file in tqdm(enumerate(filelist_335)): 469 | Xd = Map(file) 470 | fn2 = file[-26:].split("_")[0].replace("AIA","") 471 | datestring = "%s-%s-%s" % (fn2[:4],fn2[4:6],fn2[6:8]) 472 | wavelength = int(file[-26:].split("_")[-1].replace(".fits","")) 473 | correction = degrads[wavelength][datestring] 474 | 475 | for key in Xd.meta: 476 | if key != 'keycomments' and key != 'simple': 477 | vars()[key].append(Xd.meta[key]) 478 | deg_cor.append(correction) 479 | pixlunit.append('DN/s') 480 | 481 | X = Xd.data 482 | validMask = 1.0 * (X > 0) 483 | X[np.where(X<=0.0)] = 0.0 484 | expTime = max(Xd.meta['EXPTIME'],1e-2) 485 | rad = Xd.meta['RSUN_OBS'] 486 | scale_factor = trgtAS/rad 487 | t = (X.shape[0]/2.0)-scale_factor*(X.shape[0]/2.0) 488 | XForm = skimage.transform.SimilarityTransform(scale=scale_factor,translation=(t,t)) 489 | Xr = skimage.transform.warp(X,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 490 | Xm = skimage.transform.warp(validMask,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 491 | Xr = np.divide(Xr,(Xm+1e-8)) 492 | Xr = Xr / (expTime*correction) 493 | Xr = skimage.transform.downscale_local_mean(Xr,(divideFactor,divideFactor)) 494 | Xr = Xr.astype('float32') 495 | aia335[fn,:,:]=Xr 496 | 497 | for key in Xd.meta: 498 | if key != 'keycomments' and key != 'simple': 499 | aia335.attrs[key.upper()]=vars()[key] 500 | 501 | aia335.attrs['NAXIS1'] = list(np.asarray(naxis1, dtype=np.float64) / divideFactor) 502 | aia335.attrs['NAXIS2'] = list(np.asarray(naxis2, dtype=np.float64) / divideFactor) 503 | aia335.attrs['CDELT1'] = list(np.asarray(cdelt1, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 504 | aia335.attrs['CDELT2'] = list(np.asarray(cdelt2, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 505 | aia335.attrs['R_SUN'] = list(np.asarray(r_sun, dtype=np.float64) / (4. * divideFactor) * trgtAS / rsun_obs) 506 | aia335.attrs['X0_MP'] = list(np.asarray(x0_mp, dtype=np.float64) / (4. * divideFactor)) 507 | aia335.attrs['Y0_MP'] = list(np.asarray(y0_mp, dtype=np.float64) / (4. * divideFactor)) 508 | aia335.attrs['CRPIX1'] = list(np.asarray(crpix1, dtype=np.float64) / divideFactor) 509 | aia335.attrs['CRPIX2'] = list(np.asarray(crpix2, dtype=np.float64) / divideFactor) 510 | aia335.attrs['DEG_COR'] = list(np.asarray(deg_cor, dtype=np.float64)) 511 | aia335.attrs['PIXLUNIT'] = list(pixlunit) 512 | 513 | # Process 94A 514 | Xd = Map(filelist_94[0]) 515 | for key in Xd.meta: 516 | if key != 'keycomments' and key != 'simple': 517 | vars()[key] = [] 518 | deg_cor = [] 519 | pixlunit = [] 520 | 521 | for fn,file in tqdm(enumerate(filelist_94)): 522 | Xd = Map(file) 523 | fn2 = file[-26:].split("_")[0].replace("AIA","") 524 | datestring = "%s-%s-%s" % (fn2[:4],fn2[4:6],fn2[6:8]) 525 | wavelength = int(file[-26:].split("_")[-1].replace(".fits","")) 526 | correction = degrads[wavelength][datestring] 527 | 528 | for key in Xd.meta: 529 | if key != 'keycomments' and key != 'simple': 530 | vars()[key].append(Xd.meta[key]) 531 | deg_cor.append(correction) 532 | pixlunit.append('DN/s') 533 | 534 | X = Xd.data 535 | validMask = 1.0 * (X > 0) 536 | X[np.where(X<=0.0)] = 0.0 537 | expTime = max(Xd.meta['EXPTIME'],1e-2) 538 | rad = Xd.meta['RSUN_OBS'] 539 | scale_factor = trgtAS/rad 540 | t = (X.shape[0]/2.0)-scale_factor*(X.shape[0]/2.0) 541 | XForm = skimage.transform.SimilarityTransform(scale=scale_factor,translation=(t,t)) 542 | Xr = skimage.transform.warp(X,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 543 | Xm = skimage.transform.warp(validMask,XForm.inverse,preserve_range=True,mode='edge',output_shape=(X.shape[0],X.shape[0])) 544 | Xr = np.divide(Xr,(Xm+1e-8)) 545 | Xr = Xr / (expTime*correction) 546 | Xr = skimage.transform.downscale_local_mean(Xr,(divideFactor,divideFactor)) 547 | Xr = Xr.astype('float32') 548 | aia94[fn,:,:]=Xr 549 | 550 | for key in Xd.meta: 551 | if key != 'keycomments' and key != 'simple': 552 | aia94.attrs[key.upper()]=vars()[key] 553 | 554 | aia94.attrs['NAXIS1'] = list(np.asarray(naxis1, dtype=np.float64) / divideFactor) 555 | aia94.attrs['NAXIS2'] = list(np.asarray(naxis2, dtype=np.float64) / divideFactor) 556 | aia94.attrs['CDELT1'] = list(np.asarray(cdelt1, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 557 | aia94.attrs['CDELT2'] = list(np.asarray(cdelt2, dtype=np.float64) * divideFactor * rsun_obs / trgtAS) 558 | aia94.attrs['R_SUN'] = list(np.asarray(r_sun, dtype=np.float64) / (4. * divideFactor) * trgtAS / rsun_obs) 559 | aia94.attrs['X0_MP'] = list(np.asarray(x0_mp, dtype=np.float64) / (4. * divideFactor)) 560 | aia94.attrs['Y0_MP'] = list(np.asarray(y0_mp, dtype=np.float64) / (4. * divideFactor)) 561 | aia94.attrs['CRPIX1'] = list(np.asarray(crpix1, dtype=np.float64) / divideFactor) 562 | aia94.attrs['CRPIX2'] = list(np.asarray(crpix2, dtype=np.float64) / divideFactor) 563 | aia94.attrs['DEG_COR'] = list(np.asarray(deg_cor, dtype=np.float64)) 564 | aia94.attrs['PIXLUNIT'] = list(pixlunit) 565 | -------------------------------------------------------------------------------- /eve_npy_to_zarr.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Convert the SDO/EVE .npy files of SDOML to .zarr files. 3 | 4 | import numpy as np 5 | from astropy.time import Time 6 | import matplotlib.pyplot as plt 7 | import pandas as pd 8 | import zarr 9 | from numcodecs import Blosc, Delta 10 | 11 | 12 | eve_irradiance = np.load('./EVE/irradiance.npy') 13 | eve_jd = np.load('./EVE/jd.npy') 14 | eve_logt = np.load('./EVE/logt.npy') 15 | eve_name = np.load('./EVE/name.npy', allow_pickle=True) 16 | eve_wavelength = np.load('./EVE/wavelength.npy') 17 | 18 | t = Time(eve_jd, format='jd') 19 | t.format = 'iso' 20 | 21 | store = zarr.DirectoryStore('eve.zarr') 22 | compressor = Blosc(cname='zstd', clevel=5, shuffle=Blosc.BITSHUFFLE) 23 | root = zarr.group(store=store,overwrite=True) 24 | ints = root.create_group('MEGS-A') 25 | time = ints.create_dataset('Time',shape=(np.shape(eve_irradiance)[0]),dtype='