#!/usr/bin/env python3 import sys import io import tarfile import argparse import numpy as np import ucf parser = argparse.ArgumentParser(description='Reads an ucf.tar archive, downsamples it and saves it to a new ucf.tar archive. Can be used as a pipe.') parser.add_argument("-c", "--chunks", metavar='file',nargs='?', type=int, default=None, help="number of chunks [default: not chunked]", action="store") parser.add_argument("-i", "--infile", metavar='file',nargs='?', default=None, help="name of the input file [default: stdin]", action="store") parser.add_argument("-o", "--outfile", metavar='file',nargs='?', default=None, help="name of the output file [default: stdout]", action="store") parser.add_argument("-n", "--nskip", metavar='N',nargs='?', type=int, default=2, help="keep every Nth grid point [default: 2]", action="store") parser.add_argument("-sp", "--single-precision", help="output data in single-precision? [default: False]", action="store_true") args = parser.parse_args() nchunk = args.chunks nskip = args.nskip file_in = args.infile file_out = args.outfile saveSinglePrecision = args.single_precision if nchunk is None: if file_in is None: istream = tarfile.open(fileobj=sys.stdin.buffer,mode='r|',bufsize=512*1024**2,ignore_zeros=True) else: filehandle_in = open(file_in,'rb') istream = tarfile.open(fileobj=filehandle_in,mode='r') else: if file_in is None: raise ValueError('Chunked mode only works with input file, not stream') else: ichunk = 0 filehandle_in = open(file_in+'.{:d}'.format(ichunk),'rb') istream = tarfile.open(fileobj=filehandle_in,mode='r') if file_out is None: ostream = tarfile.open(fileobj=sys.stdout.buffer,mode='w|',bufsize=512*1024**2,pax_headers=tarfile.USTAR_FORMAT) else: filehandle_out = open(file_out,'wb') ostream = tarfile.open(fileobj=filehandle_out,mode='w',pax_headers=tarfile.USTAR_FORMAT) while True: iinfo = istream.next() if iinfo is None: if nchunk is not None: if ichunk+11: islice = [ii-ibeg+ighost for ii in range(ibeg,ibeg+nxl) if (ii-1)%nskip==0] jslice = [ii-jbeg+ighost for ii in range(jbeg,jbeg+nyl) if (ii-1)%nskip==0] kslice = [ii-kbeg+ighost for ii in range(kbeg,kbeg+nzl) if (ii-1)%nskip==0] data = data[np.ix_(islice,jslice,kslice)] ibeg = (islice[0]+ibeg-ighost)//nskip+1 jbeg = (jslice[0]+jbeg-ighost)//nskip+1 kbeg = (kslice[0]+kbeg-ighost)//nskip+1 (nxl,nyl,nzl) = data.shape nxg = (nxg-1)//nskip+1 nyg = (nyg-1)//nskip+1 nzg = (nzg-1)//nskip+1 params_out = list(params_in) if nskip>1: params_out[0] = 0 params_out[1:4] = (ibeg,jbeg,kbeg) params_out[4:7] = (nxl,nyl,nzl) params_out[7:10] = (nxg,nyg,nzg) if saveSinglePrecision: data = data.astype(np.float32,casting='same_kind') ucfhandle.addDatasetToBuffer(data,params=params_out,step=1,dset=iset+1) ucfbytes_out += ucfhandle.flushBuffer() ucfhandle.close() if 'scal.' in iinfo.name: ucfhandle = ucf.UCF(file=ucfbytes_in,verbosity=False) ucfhandle.copyFileHeaderToBuffer() ucfhandle.copyStepToBuffer(1,step_out=1,recursive=False) for iset in range(0,ucfhandle.NumDataset): (data,params_in) = ucfhandle.readSet(step=1,dset=iset+1) ighost = params_in[0] (ibeg,jbeg,kbeg) = params_in[1:4] (nxl,nyl,nzl) = params_in[4:7] (nxg,nyg,nzg) = params_in[7:10] data = data.reshape((nxl+2*ighost,nyl+2*ighost,nzl+2*ighost),order='F') if nskip>1: islice = [ii-ibeg+ighost for ii in range(ibeg,ibeg+nxl) if (ii-1)%nskip==0] jslice = [ii-jbeg+ighost for ii in range(jbeg,jbeg+nyl) if (ii-1)%nskip==0] kslice = [ii-kbeg+ighost for ii in range(kbeg,kbeg+nzl) if (ii-1)%nskip==0] data = data[np.ix_(islice,jslice,kslice)] ibeg = (islice[0]+ibeg-ighost)//nskip+1 jbeg = (jslice[0]+jbeg-ighost)//nskip+1 kbeg = (kslice[0]+kbeg-ighost)//nskip+1 (nxl,nyl,nzl) = data.shape nxg = (nxg-1)//nskip+1 nyg = (nyg-1)//nskip+1 nzg = (nzg-1)//nskip+1 params_out = list(params_in) if nskip>1: params_out[0] = 0 params_out[1:4] = (ibeg,jbeg,kbeg) params_out[4:7] = (nxl,nyl,nzl) params_out[7:10] = (nxg,nyg,nzg) if saveSinglePrecision: data = data.astype(np.float32,casting='same_kind') ucfhandle.addDatasetToBuffer(data,params=params_out,step=1,dset=iset+1) ucfbytes_out += ucfhandle.flushBuffer() ucfhandle.close() oinfo = tarfile.TarInfo(name=iinfo.name) oinfo.size = len(ucfbytes_out) ostream.addfile(oinfo,fileobj=io.BytesIO(ucfbytes_out)) istream.close() ostream.close() if file_in is not None: filehandle_in.close() if file_out is not None: filehandle_out.close()