/* this JSOC module is a combination of 3 SOI modules: v2helio, helio2mlat, qdotprod * ported by Tim Larson * removes check on mapbmin, mapbmax, and maprows, these keywords are no longer carried */ /* * v2helio.c ~soi/(version)/src/modules/v2helio.c * * This module interpolates CCD velocity data to estimate values that * would be obtained at specified equal increments of heliographic * longitude and sine of latitude. Apodization and corrections for * solar rotation and limbshift are included. * * Responsible: Kay Leibrand KLeibrand@solar.Stanford.EDU * * Bugs: * This module is under development. Look for ??? in comments. * * Planned updates: * Decide when and where and if default values should be used. * */ /* * helio2mlat.c ~soi/(version)/src/modules/helio2mlat.c * * Description: * Adapted by Kay Leibrand from pipeLNU shtfft * fft by map_rows. Use FORTRAN library Cmlib for float version. * extends data to 360 degrees prior to transform but only saves * cols up to lmax. Performs transpose needed prior to dotprod. * * Responsible: Kay Leibrand KLeibrand@solar.Stanford.EDU * * Bugs: * This module is under development. Look for ??? in comments. * * Planned updates: * Restructure to use functions? * Refine parameter definitions and names to be consistent with * new keywords and ancillary data flow. * Fix phase * */ /* * qdotprod.c ~soi/(version)/src/modules/qdotprod.c * * Description: * Conversion of Jesper Schou's FORTRAN q(uick)dotprod to C * from file ~schou/testdot/testdot4c.f * uses FORTRAN functions from blas library * contains optimizations, calculates masks, allows "chunking" in l * * Responsible: Kay Leibrand KLeibrand@solar.Stanford.EDU * * Bugs: * Inadequate checks for consistency between data specifications, * i.e. dataset names, and LMIN, LMAX, LCHUNK parameters. * This module is under development. Look for ??? and TBD in comments. * Normalization in plm's is different from PHS pipeLNU * * Planned updates: * Fix known bugs. * Use a consistent pointer style, i.e. pointer arith vs [] * Restructure to use functions. * Refine parameter definitions and names to be consistent with * new keywords and ancillary data flow. * * Revision history is at end of file. */ /* Normalization of the resulting time-series when norm != 0: Let the observed surface behaviour of an oscillation be given by Re(exp(-i\omega t) Y_l^m (\theta,\phi)) with (Y_l^m)^2 normalized to have an average of 1 over the unit sphere (this is 4\pi times the usual definition where the integral is 1). Assume that the whole (4\pi) Sun is observed with no velocity projection factor. Then the resulting time series is given by exp(-i\omega t). This is equivalent to preserving the rms value of the real parts of the oscillations. And maybe I got the implementation straight. */ #include #include #include #include #include #include #include #include "jsoc_main.h" #include "fstats.h" #include "drms_dsdsapi.h" #include "errlog.h" #include "projection.h" #include "atoinc.h" #define ARRLENGTH(ARR) (sizeof(ARR)/sizeof(ARR[0])) #define PI (M_PI) #define absval(x) (((x) < 0) ? (-(x)) : (x)) #define minval(x,y) (((x) < (y)) ? (x) : (y)) #define maxval(x,y) (((x) < (y)) ? (y) : (x)) #define very_small (1.0e-30) #define is_very_small(x) (absval(x) < very_small) #define is_even(x) (!((x)%2)) #define is_odd(x) ((x)%2) #define RADSINDEG (PI/180) #define ARCSECSINRAD (3600*180/PI) #define DAYSINYEAR (365.2425) #define SECSINDAY (86400) #define TAU_A (499.004783806) // light travel time in seconds, = 1 AU/c //#define TAU_A (499.004782) // this value used in old v2helio #define TCARR (25.38) // days #define RTRUE (6.96000000e8) // meters #define AU (149597870691) // meters/au //#define AU (1.49597870e11) // this value used in old v2helio #define QUAL_NODATA (0x80000000) #define QUAL_MIXEDCALVER (0x00000001) #define kNOTSPECIFIED "not specified" char *module_name = "jv2ts"; char *cvsinfo_jv2ts = "cvsinfo: $Header: /home/cvsuser/cvsroot/JSOC/proj/globalhs/apps/jv2ts.c,v 1.25 2015/05/20 19:15:47 tplarson Exp $"; ModuleArgs_t module_args[] = { // these inputs are common to all modules {ARG_STRING, "in", NULL, "input data records"}, {ARG_STRING, "tsout", kNOTSPECIFIED, "output data series"}, {ARG_STRING, "segin", kNOTSPECIFIED, "input data segment"}, {ARG_STRING, "segout", kNOTSPECIFIED, "output data segment"}, {ARG_STRING, "histlink", "HISTORY", "name of link to ancillary dataseries for processing metadata. specify \"none\" to suppress warning messages."}, {ARG_STRING, "srclink", "SRCDATA", "name of link to source data"}, // used only for jv2helio and jhelio2mlat output {ARG_STRING, "v2hout", kNOTSPECIFIED, "output data series for jv2helio"}, {ARG_STRING, "h2mout", kNOTSPECIFIED, "output data series for jhelio2mlat"}, {ARG_INT, "PERM", "1", "set to 0 for transient records, nonzero for permanent records"}, {ARG_INT, "VERB", "1", "option for level of verbosity: 0 gives only error and warning messages; >0 prints messages outside of loop; >1 prints messages inside loop; >2 for debugging output"}, {ARG_INT, "FORCEOUTPUT", "0", "option to specify behavior on missing inputs; 0 gives an error on missing or duplicate inputs, >0 makes outputs regardless"}, {ARG_STRING, "TAG", "none", "this parameter sets a keyword of the same name to the same value, usually used as an additional primekey"}, {ARG_STRING, "VERSION", kNOTSPECIFIED, "this parameter sets a keyword of the same name to the same value, useful for selecting obsolete records"}, {ARG_INT, "CALVERKEY", "2", "short integer bit mask determining which 4-bit fields of CALVER64 are permitted to change on input. set the bit to disallow change of the corresponding nybble."}, // these are from jqdotprod {ARG_INT, "LMIN", "0", "minimum l in output"}, // {ARG_INT, "LMAX", "0", "maximum l in output, take from input if 0"}, /* if 0, default is LMAX of in_sds */ {ARG_INT, "LCHUNK", "0", "increment in l on output, default is lmax+1"}, /* if 0, is LMAX+1 */ {ARG_INT, "NORM", "1", "set to nonzero to use cnorm=sinbdelta*sqrt(2) in sgemm call, otherwise use cnorm=1"}, /* Uses old norm if =0, see below */ {ARG_TIME, "TSTART", NULL, "start time of first output record"}, {ARG_STRING, "TTOTAL", NULL, "total length of time in output"}, {ARG_STRING, "TCHUNK", kNOTSPECIFIED, "length of output timeseries"}, // these are from jhelio2mlat {ARG_INT, "LMAX", "300", "maximum l (maximum m) in the output, cannot be greater than MAPMMAX", NULL}, {ARG_INT, "SUBMEAN", "0", "nonzero subtracts mean of input image", NULL}, {ARG_INT, "NORMLIZE", "0", "nonzero multiplies by sqrt((fraction nonmissing)/2) for each row", NULL}, {ARG_INT, "CENTLONG", "1", "nonzero centers the longitude Fourier transform on the center of the remapped image", NULL}, {ARG_INT, "ZEROMISS", "0", "zero sets any row containing a NaN to DRMS_MISSING", NULL}, {ARG_INT, "LGAPOD", "0", "nonzero apodizes in longitude", NULL}, {ARG_DOUBLE, "LGAPMIN", "60.0", "start of longitude apodization, degrees", NULL}, {ARG_DOUBLE, "LGAPWIDT", "10.0", "width of longitude apodization, degrees", NULL}, // these are from jv2helio {ARG_INT, "MAPMMAX", "1536", "determines mapcols", ""}, /* determines mapcols, default value is 3*512 */ {ARG_INT, "SINBDIVS", "512", "number of increments in sin latitude from 0 to 1", ""}, /* # of = increments in sinB from sin(0) to sin(PI/2) */ {ARG_FLOAT, "MAPRMAX", "0.95", "maximum image radius", ""}, {ARG_INT, "NAN_BEYOND_RMAX", "0", "set to nonzero to set output to DRMS_MISSING outside MAPRMAX, otherwise uses 0.0 outside MAPRMAX"}, /* Non 0 sets data outside RMAX MISSING */ {ARG_FLOAT, "MAPLGMAX", "72.0", "longitude maximum, degrees", ""}, /* degrees */ {ARG_FLOAT, "MAPLGMIN", "-72.0", "longitude minimum, degrees", ""}, {ARG_FLOAT, "MAPBMAX", "72.0", "latitude maximum, degrees, also used for minimum", ""}, {ARG_INT, "LGSHIFT", "0", "option for longitude shift: 0=none; 1=fixed rate; 2=nearest degree; 3=nearest tenth of a degree", ""}, /* 0=none; 1=fixed rate; 2=nearest Degree */ {ARG_TIME, "REF_T0", "1987.01.03_17:31:12_TAI", "reference time for computing fixed rate longitude shift", ""}, {ARG_FLOAT, "REF_L0", "0.0", "reference longitude for computing fixed rate longitude shift ", ""}, {ARG_FLOAT, "SOLAR_P", "999.0", "P-angle; if unset, taken from keywords", ""}, /* can't use D_MISSING here */ {ARG_FLOAT, "PSIGN", "1.0", "sign of SOLAR_P", ""}, /* Sign of P. For MWO data. */ {ARG_FLOAT, "PERR", "0.0", "fixed P-angle error, likely -0.22", ""}, /* Fixed P-angle error. Maybe -0.22. */ {ARG_FLOAT, "IERR", "0.0", "error in Carrington inclination, likely -0.10", ""}, /* Error in Carrington inclination. Maybe -0.10. */ {ARG_TIME, "REF_TB0", "2001.06.06_06:57:22_TAI", "reference time for computing correction to P and B angles, roughly when B0=0", ""}, {ARG_INT, "INTERPO", "1", "option for interpolation: 0=bilinear; 1=cubic convolution", ""}, /* 2 methods - see soi_fun.h */ {ARG_INT, "APODIZE", "0", "option for apodization: 0=none; 1=use true solar coordinates; 2=use ideal solar coordinates (b0=0)", ""}, /* see soi_fun.h or apodize.c */ {ARG_FLOAT, "APINNER", "0.90", "start of apodization in fractional image radius", ""}, /* start of apodization */ {ARG_FLOAT, "APWIDTH", "0.05", "width of apodization in fractional image radius", ""}, /* width of apodization */ {ARG_INT, "APEL", "0", "set to nonzero for elliptical apodization described by APX and APY", ""}, /* do elliptical apodization described by apx and apy */ {ARG_FLOAT, "APX", "1.00", "divide the x position by this before applying apodization", ""}, /* divide the x position by this before applying apodization */ {ARG_FLOAT, "APY", "1.00", "divide the y position by this before applying apodization", ""}, /* divide the y position by this before applying apodization */ {ARG_INT, "VCORLEV", "2", "option for velocity correction: 0=none; 1=subtract a model of differential rotation; 2=also divide by line of sight projection factor for purely radial velocities", ""}, /* 3 levels - see soi_fun.h*/ {ARG_INT, "MCORLEV", "0", "option for magnetic correction: 0=none; 1=line of sight; 2=radial", ""}, /* 2 levels - see soi_fun.h*/ {ARG_INT, "MOFFSETFLAG", "0", "set to nonzero to get BFITZERO from input record and subtract from data before interpolating", ""}, /* 1=apply BFITZERO correction*/ {ARG_FLOAT, "OUTSCALE", "1.0", "bscale to use for output", ""}, /* scale for output */ {ARG_FLOAT, "OUTBIAS", "0.0", "bzero to use for output", ""}, /* bias for scaled output */ {ARG_INT, "DISTORT", "0", "option for distortion correction: 0=none; 1=full disk(fd) data; 2=vector-weighted(vw) data", ""}, /* 0 for none, 1 for FD, 2 for vw */ {ARG_FLOAT, "CUBIC", "7.06E-9", "cubic distortion in fd units", ""}, /* Cubic distortion in FD units */ {ARG_FLOAT, "TILTALPHA", "2.59", "tilt of CCD, degrees", ""}, /* TILT of CCD in degrees */ {ARG_FLOAT, "TILTBETA", "56.0", "direction of CCD tilt, degrees", ""}, /* Direction of TILT in degrees */ {ARG_FLOAT, "TILTFEFF", "12972.629", "effective focal length", ""}, /* Effective focal length */ {ARG_INT, "OFLAG", "0", "set to nonzero to force reading orientation from keyword, otherwise \"SESW\" is assumed)", ""}, /* Non 0 skips checko (SESW assumed) */ {ARG_INT, "DATASIGN", "0", "value to multiply data; set to 0 to take DATASIGN from keyword, or 1.0 if not found", ""}, /* Non 0 forces datasign to value*/ {ARG_INT, "MAXMISSVALS", "0", "if >0, this becomes threshold on MISSVALS from keyword", ""}, /* max. allowed MISSING pixels */ {ARG_INT, "CARRSTRETCH", "0", "set to nonzero to correct for differential rotation according to DIFROT_[ABC]", ""}, /* 0 - don't correct for diff rot, 1 - correct */ {ARG_FLOAT, "DIFROT_A", "13.562", "A coefficient in differential rotation adjustment (offset)", ""}, /* A coefficient in diff rot adj (offset) */ {ARG_FLOAT, "DIFROT_B", "-2.04", "B coefficient (to sin(lat) ^ 2)", ""}, /* B coefficient (to sin(lat) ^ 2) */ {ARG_FLOAT, "DIFROT_C", "-1.4875", "C coefficient (to sin(lat) ^ 4)", ""}, /* C coefficient (to sin(lat) ^ 4) */ {ARG_END} }; #include "saveparm.c" #include "timing.c" #include "set_history.c" #include "calversfunctions.c" int SetDistort(int dist, double cubic, double alpha, double beta, double feff, LIBPROJECTION_Dist_t *dOut); int obs2helio(float *V, float *U, int xpixels, int ypixels, double x0, double y0, double BZero, double P, double S, double rsun, double Rmax, int interpolation, int cols, int rows, double Lmin, double Ldelta, double Ladjust, double sinBdelta, double smajor, double sminor, double sangle, double xscale, double yscale, const char *orientation, int mag_correction, int velocity_correction, double obs_vr, double obs_vw, double obs_vn, double vsign, int NaN_beyond_rmax, int carrStretch, const LIBPROJECTION_Dist_t *distpars, float diffrotA, float diffrotB, float diffrotC, LIBPROJECTION_RotRate_t *rRates, int size); int apodize(float *data, double b0, int cols, int rows, double Lmin, double Ldelta, double sinBdelta, int apodlevel, double apinner, double apwidth, int apel, double apx, double apy); void setplm2(int lmin,int lmax,int m,long nx,int *indx,double *x,long nplm,double *plm,double *dplm); //char *getshtversion(void); /* forward decls for fortran functions */ void scopy_(int *, float *, int *, float *, int *); void setplm_(int *, int *, int *, int *, int *, double *, int *, double *); void sgemm_(); /* give up */ typedef enum { V2HStatus_Success, V2HStatus_MissingParameter, V2HStatus_IllegalTimeFormat, V2HStatus_TimeConvFailed, V2HStatus_Unimplemented, V2HStatus_IllegalOrientation } V2HStatus_t; static void CheckO(const char *orientation, V2HStatus_t *stat) { /* check for legal orientation string */ static char o[16]; char *c = o; if(!orientation) { *stat = V2HStatus_MissingParameter; } else if (4 != sscanf(orientation, "%[NS]%[EW]%[NS]%[EW]", c++, c++, c++, c++)) { *stat = V2HStatus_IllegalOrientation; } else if ((o[0] == o[2]) && (o[1] == o[3])) { *stat = V2HStatus_IllegalOrientation; } else if ((o[0] !=o [2]) && (o[1] != o[3])) { *stat = V2HStatus_IllegalOrientation; } else { *stat = V2HStatus_Success; } } static inline void ParameterDef(int status, char *pname, double defaultp, double *p, long long recnum, int verbflag) { /* logs warning and sets parameter to default value */ if (status != 0) { *p = defaultp; if (verbflag) fprintf(stderr, "WARNING: default value %g used for %s, status = %d, recnum = %lld\n", defaultp, pname, status, recnum); } } #define PARAMETER_ERROR(PNAME) \ if (status != DRMS_SUCCESS) \ { \ fprintf(stderr, "ERROR: problem with required keyword %s, status = %d, T_REC = %s, recnum = %lld, histrecnum = %lld\n", PNAME, status, trecstr, inrec->recnum, histrecnum); \ drms_free_array(inarr); \ return 0; \ } int DoIt(void) { int newstat=0; DRMS_RecChunking_t chunkstat = kRecChunking_None; int fetchstat = DRMS_SUCCESS; int status = DRMS_SUCCESS; char *inrecquery = NULL; char *outseries = NULL; char *segnamein = NULL; char *segnameout = NULL; DRMS_RecordSet_t *inrecset = NULL; DRMS_Record_t *inrec = NULL; DRMS_Record_t *outrec = NULL; DRMS_Segment_t *segin = NULL; DRMS_Segment_t *segout = NULL; DRMS_Array_t *inarr = NULL; DRMS_Array_t *outarr = NULL; DRMS_Type_t usetype = DRMS_TYPE_FLOAT; DRMS_RecLifetime_t lifetime; long long histrecnum=-1; int length[2]; double wt0, wt1, wt2, wt3, wt; double ut0, ut1, ut2, ut3, ut; double st0, st1, st2, st3, st; double ct0, ct1, ct2, ct3, ct; TIME trec, tnow, UNIX_epoch = -220924792.000; /* 1970.01.01_00:00:00_UTC */ char trecstr[100], tstartstr[100]; int quality; float *v2hptr, *h2mptr; // from jqdotprod, norm changed to normflag float *oddpart, *evenpart, *inptr, *workptr, *mptr, *outptr; float *folded, *masks, *real4evenl, *real4oddl, *imag4evenl, *imag4oddl, *outx; /* used for setting up plm's */ double *plm, *saveplm, *latgrid; int *indx; double sinBdelta; double *plmptr; float *maskptr; int nsn, fournsn, snx, maxnsn; int lchunksize, lchunkfirst, lchunklast, lchunk, l; int lmin, lmax; int msize, mx, foldedsize; int maprows, nlat, imagesize, latx, poslatx, neglatx, moffset, nlatx; int i, m, modd, meven; int lfirst, llast, ifirst, ilast, lstart, ldone; int lfirsteven, llasteven, nevenl, lfirstodd, llastodd, noddl; int fromoffset, tooffset, imageoffset; int increment1 = 1; /* for scopy call */ int increment2 = 2; /* for scopy call */ /* arguments for sgemm call */ char transpose[] = "t"; char normal[] = "n"; float one = 1.0; float zero = 0.0; int normflag; float cnorm; /* Constant to get proper normalization. */ double tstart, tepoch, tstep, tround, cadence, nseconds, chunksecs, cadence0; char *ttotal, *tchunk; int nrecs, irec, trecind, bc, iset, ntimechunks; int *bad; int ndt; // from jhelio2mlat, i, lmax duplicated. double mean, norm=1.0, normx; int subtract_mean, normalize, cent_long, zero_miss, lgapod; double lgapmin, lgapwidt, lgapmax, lon; int row, col; int lfft, mapped_lmax; int mapcols2; int nfft, nmean, nok, nout; float *buf, *bp, *ip, *inp, *op, *outp, *weight, *wp; float *wbuf; fftwf_plan fftwp; // from jv2helio, row, mapped_lmax, maprows, sinBdelta duplicated V2HStatus_t vstat = V2HStatus_Success; const char *orientationdef = "SESW "; char *orientation = NULL; int paramsign; int longitude_shift, velocity_correction, interpolation, apodization; int mag_correction; int mag_offset; int sinb_divisions, mapcols, nmax, nmin; int carrStretch = 0; float diffrotA = 0.0; float diffrotB = 0.0; float diffrotC = 0.0; double tobs, tmearth, tref, trefb0; double smajor, sminor, sangle; double xscale, yscale, imagescale; int xpixels, ypixels, pixels; double obs_vr, obs_vw, obs_vn; double b0, bmax, bmin; double longmax, longmin, longmax_adjusted, longmin_adjusted, longinterval; double p0, p, rmax; double ierr, perr, psign; double x0, y0; double obsdist, longshift, obsl0, refl0, mapl0, longrate, rtrue, rsun, S; double rsunDef, rsunobs; int obsCR; int apel; double apinner, apwidth, apx, apy; double scale, bias; double colsperdeg; double satrot, instrot; double dsignout, vsign; int distsave; double cubsave, tiltasave, tiltbsave, tiltfsave; LIBPROJECTION_Dist_t distP; int errbufstat=setvbuf(stderr, NULL, _IONBF, BUFSIZ); int outbufstat=setvbuf(stdout, NULL, _IONBF, BUFSIZ); wt0=getwalltime(); ct0=getcputime(&ut0, &st0); inrecquery = (char *)cmdparams_save_str(&cmdparams, "in", &newstat); outseries = (char *)cmdparams_save_str(&cmdparams, "tsout", &newstat); int tsflag = strcmp(kNOTSPECIFIED, outseries); segnamein = (char *)cmdparams_save_str(&cmdparams, "segin", &newstat); segnameout = (char *)cmdparams_save_str(&cmdparams, "segout", &newstat); int seginflag = strcmp(kNOTSPECIFIED, segnamein); int segoutflag = strcmp(kNOTSPECIFIED, segnameout); int verbflag = cmdparams_save_int(&cmdparams, "VERB", &newstat); int permflag = cmdparams_save_int(&cmdparams, "PERM", &newstat); if (permflag) lifetime = DRMS_PERMANENT; else lifetime = DRMS_TRANSIENT; int forceoutput = cmdparams_save_int(&cmdparams, "FORCEOUTPUT", &newstat); char *tag = (char *)cmdparams_save_str(&cmdparams, "TAG", &newstat); char *version = (char *)cmdparams_save_str(&cmdparams, "VERSION", &newstat); int verflag = strcmp(kNOTSPECIFIED, version); unsigned short calverkey = (unsigned short)cmdparams_save_int(&cmdparams, "CALVERKEY", &newstat); char *histlinkname = (char *)cmdparams_save_str(&cmdparams, "histlink", &newstat); char *srclinkname = (char *)cmdparams_save_str(&cmdparams, "srclink", &newstat); char *v2hout = (char *)cmdparams_save_str(&cmdparams, "v2hout", &newstat); char *h2mout = (char *)cmdparams_save_str(&cmdparams, "h2mout", &newstat); int v2hflag = strcmp(kNOTSPECIFIED, v2hout); int h2mflag = strcmp(kNOTSPECIFIED, h2mout); int histflag = strncasecmp("none", histlinkname, 4); if (!v2hflag && !h2mflag && !tsflag) { fprintf(stderr, "ERROR: no outputs specified.\n"); return 1; } lmin=cmdparams_save_int(&cmdparams, "LMIN", &newstat); lmax=cmdparams_save_int(&cmdparams, "LMAX", &newstat); lchunksize=cmdparams_save_int(&cmdparams, "LCHUNK", &newstat); normflag=cmdparams_save_int(&cmdparams, "NORM", &newstat); tstart=cmdparams_save_time(&cmdparams, "TSTART", &newstat); sprint_time(tstartstr, tstart, "TAI", 0); ttotal=(char *)cmdparams_save_str(&cmdparams, "TTOTAL", &newstat); nseconds=atoinc(ttotal); /* if (strcmp(kNOTSPECIFIED, ttotal)) { nseconds=atoinc(ttotal); } else nseconds=0.0; */ /* status=drms_names_parseduration(&ttotal, &nseconds, 1); if (status != DRMS_SUCCESS) { fprintf(stderr, "ERROR: problem parsing TTOTAL, = %s\n", ttotal); return 1; } */ tchunk=(char *)cmdparams_save_str(&cmdparams, "TCHUNK", &newstat); if (strcmp(kNOTSPECIFIED, tchunk)) { chunksecs=atoinc(tchunk); /* status=drms_names_parseduration(&tchunk, &chunksecs, 1); if (status != DRMS_SUCCESS) newstat = newstat | CPSAVE_UNKNOWN_ERROR; */ } else if (!tsflag) { fprintf(stderr, "ERROR: TCHUNK must be specified if no tsout is given.\n"); return 1; } else chunksecs=0.0; subtract_mean = cmdparams_save_int(&cmdparams, "SUBMEAN", &newstat); normalize = cmdparams_save_int(&cmdparams, "NORMLIZE", &newstat); /* CENTLONG=1 centers the longitude Fourier transform on the center of the remapped image */ cent_long = cmdparams_save_int(&cmdparams, "CENTLONG", &newstat); /* ZEROMISS=1 sets missing data to 0, ZEROMISS=0 fills the output row with missing */ zero_miss = cmdparams_save_int(&cmdparams, "ZEROMISS", &newstat); lgapod = cmdparams_save_int(&cmdparams, "LGAPOD", &newstat); lgapmin = cmdparams_save_double(&cmdparams, "LGAPMIN", &newstat); lgapwidt = cmdparams_save_double(&cmdparams, "LGAPWIDT", &newstat); lgapmax = lgapmin+lgapwidt; int checko = cmdparams_save_int(&cmdparams, "OFLAG", &newstat); int NaN_beyond_rmax = cmdparams_save_int(&cmdparams, "NAN_BEYOND_RMAX", &newstat); int maxmissvals = cmdparams_save_int(&cmdparams, "MAXMISSVALS", &newstat); // float beyondrmax = cmdparams_save_float(&cmdparams, "BEYONDRMAX", &newstat); carrStretch = cmdparams_save_int(&cmdparams, "CARRSTRETCH", &newstat); diffrotA = cmdparams_save_float(&cmdparams, "DIFROT_A", &newstat); diffrotB = cmdparams_save_float(&cmdparams, "DIFROT_B", &newstat); diffrotC = cmdparams_save_float(&cmdparams, "DIFROT_C", &newstat); longrate = 360.0 / TCARR - 360.0 / DAYSINYEAR; // degrees per day longrate /= SECSINDAY; // degrees per sec apodization = cmdparams_save_int(&cmdparams, "APODIZE", &newstat); apinner = cmdparams_save_double(&cmdparams, "APINNER", &newstat); apwidth = cmdparams_save_double(&cmdparams, "APWIDTH", &newstat); apel = cmdparams_save_int(&cmdparams, "APEL", &newstat); apx = cmdparams_save_double(&cmdparams, "APX", &newstat); apy = cmdparams_save_double(&cmdparams, "APY", &newstat); longitude_shift = cmdparams_save_int(&cmdparams, "LGSHIFT", &newstat); mag_correction = cmdparams_save_int(&cmdparams, "MCORLEV", &newstat); mag_offset = cmdparams_save_int(&cmdparams, "MOFFSETFLAG", &newstat); velocity_correction = cmdparams_save_int(&cmdparams, "VCORLEV", &newstat); interpolation = cmdparams_save_int(&cmdparams, "INTERPO", &newstat); paramsign = cmdparams_save_int(&cmdparams, "DATASIGN", &newstat); rmax = cmdparams_save_double(&cmdparams, "MAPRMAX", &newstat); refl0 = cmdparams_save_double(&cmdparams, "REF_L0", &newstat); distsave = cmdparams_save_int(&cmdparams, "DISTORT", &newstat); cubsave = cmdparams_save_double(&cmdparams, "CUBIC", &newstat); tiltasave = cmdparams_save_double(&cmdparams, "TILTALPHA", &newstat); tiltbsave = cmdparams_save_double(&cmdparams, "TILTBETA", &newstat); tiltfsave = cmdparams_save_double(&cmdparams, "TILTFEFF", &newstat); scale = cmdparams_save_double(&cmdparams, "OUTSCALE", &newstat); bias = cmdparams_save_double(&cmdparams, "OUTBIAS", &newstat); p0 = cmdparams_save_double(&cmdparams, "SOLAR_P", &newstat); psign = cmdparams_save_double(&cmdparams, "PSIGN", &newstat); perr = cmdparams_save_double(&cmdparams, "PERR", &newstat); ierr = cmdparams_save_double(&cmdparams, "IERR", &newstat); trefb0 = cmdparams_save_time(&cmdparams, "REF_TB0", &newstat); SetDistort(distsave, cubsave, tiltasave, tiltbsave, tiltfsave, &distP); tref = cmdparams_save_time(&cmdparams, "REF_T0", &newstat); // determine mapcols and adjust longmin and longmax */ mapped_lmax = cmdparams_save_int(&cmdparams, "MAPMMAX", &newstat); longmax = cmdparams_save_double(&cmdparams, "MAPLGMAX", &newstat); /* degrees */ longmin = cmdparams_save_double(&cmdparams, "MAPLGMIN", &newstat); /* degrees */ longinterval = (180.0) / mapped_lmax; /* degrees */ // This does not always handle the case where 1/longinterval is an integer correctly. // the next two statement do nothing, right? // why do nmin and max keep getting set with different RHSs? nmin = (int)(longmin / longinterval); // round towards 0 nmax = (int)(longmax / longinterval); // round towards 0 colsperdeg = mapped_lmax / 180.0; nmin = (int)(longmin * colsperdeg); // round towards 0 nmax = (int)(longmax * colsperdeg); // round towards 0 mapcols = nmax - nmin + 1; longmin_adjusted = nmin * longinterval; longmax_adjusted = nmax * longinterval; // determine maprows, bmax, bmin, and sinBdelta sinb_divisions = cmdparams_save_int(&cmdparams, "SINBDIVS", &newstat); sinBdelta = 1.0/sinb_divisions; bmax = cmdparams_save_double(&cmdparams, "MAPBMAX", &newstat); // degrees bmin = -bmax; nmax = (int)(sin(RADSINDEG*bmax)*sinb_divisions); // round towards 0 maprows = 2*nmax; if (normflag == 0) cnorm=1.0; else cnorm = sqrt(2.)*sinBdelta; if (lmax > mapped_lmax || lmin > lmax) { fprintf(stderr, "ERROR: must have MAPMMAX >= LMAX >= LMIN, MAPMMAX = %d, LMAX= %d, LMIN = %d\n", mapped_lmax, lmax, lmin); return 1; } if (newstat) { fprintf(stderr, "ERROR: problem with input arguments, status = %d, diagnosis follows\n", newstat); cpsave_decode_error(newstat); return 1; } else if (savestrlen != strlen(savestr)) { fprintf(stderr, "ERROR: problem with savestr, savestrlen = %d, strlen(savestr) = %d\n", savestrlen, (int)strlen(savestr)); return 1; } DRMS_Record_t *tempoutrec; DRMS_Link_t *histlink; int itest; /* // cvsinfo used to be passed in the call to set_history. now this information is encoded in CVSTAG, which is defined by a compiler flag in the make. char *cvsinfo; cvsinfo = (char *)malloc(1024); strcpy(cvsinfo,"$Header: /home/cvsuser/cvsroot/JSOC/proj/globalhs/apps/jv2ts.c,v 1.25 2015/05/20 19:15:47 tplarson Exp $"); strcat(cvsinfo,"\n"); strcat(cvsinfo,getshtversion()); */ // assume all output dataseries link to the same dataseries for HISTORY if (tsflag) { tempoutrec = drms_create_record(drms_env, outseries, DRMS_TRANSIENT, &status); if (status != DRMS_SUCCESS) { fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", outseries, status); return 1; } DRMS_Keyword_t *outkeytest = hcon_lookup_lower(&tempoutrec->keywords, "MAPMMAX"); if (outkeytest != NULL && outkeytest->info->recscope == 1) { int mapmmaxout=drms_getkey_int(tempoutrec, "MAPMMAX", &status); if (mapmmaxout != mapped_lmax) { fprintf(stderr,"ERROR: output MAPMMAX=%d does not match input parameter MAPMMAX=%d, status = %d\n", mapmmaxout, mapped_lmax, status); return 1; } } outkeytest = hcon_lookup_lower(&tempoutrec->keywords, "SINBDIVS"); if (outkeytest != NULL && outkeytest->info->recscope == 1) { int sinbdivsout=drms_getkey_int(tempoutrec, "SINBDIVS", &status); if (sinbdivsout != sinb_divisions) { fprintf(stderr,"ERROR: output SINBDIVS=%d does not match input parameter SINBDIVS=%d, status = %d\n", sinbdivsout, sinb_divisions, status); return 1; } } // set up ancillary dataseries for processing metadata if (histflag) { histlink = hcon_lookup_lower(&tempoutrec->links, histlinkname); if (histlink != NULL) { histrecnum=set_history(histlink); if (histrecnum < 0) { drms_close_record(tempoutrec, DRMS_FREE_RECORD); return 1; } } else { fprintf(stderr,"WARNING: could not find history link in output dataseries\n"); } } // these must be present in the output dataseries and variable, not links or constants char *outchecklist[] = {"T_START", "QUALITY", "LMIN", "LMAX", "NDT"}; for (itest=0; itest < ARRLENGTH(outchecklist); itest++) { DRMS_Keyword_t *outkeytest = hcon_lookup_lower(&tempoutrec->keywords, outchecklist[itest]); if (outkeytest == NULL || outkeytest->info->islink || outkeytest->info->recscope == 1) { fprintf(stderr, "ERROR: output keyword %s is either missing, constant, or a link\n", outchecklist[itest]); drms_close_record(tempoutrec, DRMS_FREE_RECORD); return 1; } } cadence0=drms_getkey_float(tempoutrec, "T_STEP", &status); tepoch=drms_getkey_time(tempoutrec, "T_START_epoch", &status); tstep=drms_getkey_float(tempoutrec, "T_START_step", &status); tround=drms_getkey_float(tempoutrec, "T_START_round", &status); if (fmod(tstart-tepoch,tstep) > tround/2) { sprint_time(trecstr, tepoch, "TAI", 0); fprintf(stderr, "ERROR: output dataseries seems incompatible with input parameters (tstep must divide tstart-tepoch): TSTART = %s, T_START_epoch = %s, tstep = %f\n", tstartstr, trecstr, tstep); drms_close_record(tempoutrec, DRMS_FREE_RECORD); return 1; } if (chunksecs == 0.0) chunksecs = tstep; else if (fmod(chunksecs,tstep)) { fprintf(stderr, "ERROR: output dataseries seems incompatible with input parameters (tstep must divide chunksecs): chunksecs = %f, tstep = %f\n", chunksecs, tstep); drms_close_record(tempoutrec, DRMS_FREE_RECORD); return 1; } drms_close_record(tempoutrec, DRMS_FREE_RECORD); } if (v2hflag) { tempoutrec = drms_create_record(drms_env, v2hout, DRMS_TRANSIENT, &status); if (status != DRMS_SUCCESS) { fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", v2hout, status); return 1; } // set up ancillary dataseries for processing metadata if (histflag && histrecnum < 0) { histlink = hcon_lookup_lower(&tempoutrec->links, histlinkname); if (histlink != NULL) { histrecnum=set_history(histlink); if (histrecnum < 0) { drms_close_record(tempoutrec, DRMS_FREE_RECORD); return 1; } } else { fprintf(stderr,"WARNING: could not find history link in output dataseries\n"); } } // these must be present in the output dataseries and variable, not links or constants char *outchecklist[] = {"T_REC", "QUALITY", "CRPIX1", "CRVAL1", "CDELT1", "CRPIX2", "CROTA2", "CDELT2" }; for (itest=0; itest < ARRLENGTH(outchecklist); itest++) { DRMS_Keyword_t *outkeytest = hcon_lookup_lower(&tempoutrec->keywords, outchecklist[itest]); if (outkeytest == NULL || outkeytest->info->islink || outkeytest->info->recscope == 1) { fprintf(stderr, "ERROR: output keyword %s is either missing, constant, or a link\n", outchecklist[itest]); drms_close_record(tempoutrec, DRMS_FREE_RECORD); return 1; } } drms_close_record(tempoutrec, DRMS_FREE_RECORD); } if (h2mflag) { tempoutrec = drms_create_record(drms_env, h2mout, DRMS_TRANSIENT, &status); if (status != DRMS_SUCCESS) { fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", h2mout, status); return 1; } // set up ancillary dataseries for processing metadata if (histflag && histrecnum < 0) { histlink = hcon_lookup_lower(&tempoutrec->links, histlinkname); if (histlink != NULL) { histrecnum=set_history(histlink); if (histrecnum < 0) { drms_close_record(tempoutrec, DRMS_FREE_RECORD); return 1; } } else { fprintf(stderr,"WARNING: could not find history link in output dataseries\n"); } } // these must be present in the output dataseries and variable, not links or constants char *outchecklist[] = {"T_REC", "QUALITY", "CRPIX1", "CDELT1", "CRPIX2", "CDELT2" }; for (itest=0; itest < ARRLENGTH(outchecklist); itest++) { DRMS_Keyword_t *outkeytest = hcon_lookup_lower(&tempoutrec->keywords, outchecklist[itest]); if (outkeytest == NULL || outkeytest->info->islink || outkeytest->info->recscope == 1) { fprintf(stderr, "ERROR: output keyword %s is either missing, constant, or a link\n", outchecklist[itest]); drms_close_record(tempoutrec, DRMS_FREE_RECORD); return 1; } } drms_close_record(tempoutrec, DRMS_FREE_RECORD); } if (fmod(nseconds,chunksecs) != 0.0) { fprintf(stderr, "ERROR: input parameters seem incompatible (chunksecs must divide totalsecs): totalsecs = %f, chunksecs = %f\n", nseconds, chunksecs); return 1; } ntimechunks=nseconds/chunksecs; inrecset = drms_open_recordset(drms_env, inrecquery, &status); if (status != DRMS_SUCCESS || inrecset == NULL) { fprintf(stderr, "ERROR: problem opening input recordset: status = %d\n", status); return 1; } int nrecsin = drms_count_records(drms_env, inrecquery, &status); if (status != DRMS_SUCCESS) { fprintf(stderr, "ERROR: problem counting input records: status = %d, nrecs = %d\n", status, nrecsin); drms_close_records(inrecset, DRMS_FREE_RECORD); return 1; } if (nrecsin == 0) { fprintf(stderr, "ERROR: input recordset contains no records. if such was intended use jretile instead.\n"); drms_close_records(inrecset, DRMS_FREE_RECORD); return 1; } //the above replaces the following. drms_open_recordset() no longer fills in the number of records. /* if (inrecset->n == 0) { fprintf(stderr, "ERROR: input recordset contains no records. if such was intended use jretile instead.\n"); drms_close_records(inrecset, DRMS_FREE_RECORD); return 1; } */ if (verbflag) printf("input recordset opened, nrecs = %d\n", nrecsin); inrec = drms_recordset_fetchnext(drms_env, inrecset, &fetchstat, &chunkstat, NULL); // these must be present in the input dataseries char *inchecklist[] = {"T_REC", "QUALITY", "T_OBS", "CRLT_OBS", "CRLN_OBS", "CADENCE", // "SAT_ROT", "INST_ROT", "IM_SCALE", "CDELT1", "CDELT2"}; DRMS_Keyword_t *inkeytest; for (itest=0; itest < ARRLENGTH(inchecklist); itest++) { inkeytest = hcon_lookup_lower(&inrec->keywords, inchecklist[itest]); if (inkeytest == NULL) { fprintf(stderr, "ERROR: required input keyword %s is missing\n", inchecklist[itest]); drms_close_records(inrecset, DRMS_FREE_RECORD); return 1; } } int readrsunref=0; double rsunref; inkeytest = hcon_lookup_lower(&inrec->keywords, "RSUN_REF"); if (inkeytest == NULL) rtrue = RTRUE/AU; else if (inkeytest->info->recscope == 1) { rsunref = drms_getkey_double(inrec, "RSUN_REF", &status); ParameterDef(status, "RSUN_REF", RTRUE, &rsunref, inrec->recnum, 1); rtrue=rsunref/AU; } else readrsunref=1; trec = drms_getkey_time(inrec, "T_REC", &status); if (status != DRMS_SUCCESS) { fprintf(stderr, "ERROR: problem with required parameter T_REC: status = %d, recnum = %lld\n", status, inrec->recnum); drms_close_records(inrecset, DRMS_FREE_RECORD); return 1; } sprint_time(trecstr, trec, "TAI", 0); cadence=drms_getkey_float(inrec, "CADENCE", &status); if (status != DRMS_SUCCESS) { fprintf(stderr, "ERROR: problem with required parameter CADENCE: status = %d, T_REC = %s, recnum = %lld\n", status, trecstr, inrec->recnum); drms_close_records(inrecset, DRMS_FREE_RECORD); return 1; } if (!forceoutput) { if (nrecsin != nseconds/cadence) { fprintf(stderr, "ERROR: input recordset does not contain a record for every slot.\n"); drms_close_records(inrecset, DRMS_FREE_RECORD); return 1; } } if (tsflag && cadence != cadence0) { fprintf(stderr, "ERROR: input CADENCE does not match output T_STEP: status = %d, T_REC = %s, recnum = %lld\n", status, trecstr, inrec->recnum); drms_close_records(inrecset, DRMS_FREE_RECORD); return 1; } nrecs=chunksecs/cadence; maxnsn=nsn=nrecs; fournsn=4*nsn; if (verbflag) printf("ntimechunks = %d, recs per timechunk = %d\n", ntimechunks, nrecs); if (trec >= tstart + nseconds) { fprintf(stderr, "ERROR: no records processed: first input record is after last output record: T_REC = %s\n", trecstr); drms_close_records(inrecset, DRMS_FREE_RECORD); return 1; } while (trec < tstart && chunkstat != kRecChunking_NoMoreRecs) { fprintf(stderr, "WARNING: input record will not be included in output: T_REC = %s, TSTART = %s \n", trecstr, tstartstr); inrec = drms_recordset_fetchnext(drms_env, inrecset, &fetchstat, &chunkstat, NULL); if (inrec != NULL) { trec = drms_getkey_time(inrec, "T_REC", &status); sprint_time(trecstr, trec, "TAI", 0); } } if (chunkstat == kRecChunking_NoMoreRecs) { fprintf(stderr,"ERROR: no records processed: last input record is before first output record: T_REC = %s\n", trecstr); drms_close_records(inrecset, DRMS_FREE_RECORD); return 1; } msize = lmax+1; if (lchunksize == 0) lchunksize = msize; nlat = maprows/2; imagesize = maprows*2*msize; /* out image could be smaller than in */ nout = 2 * (lmax + 1); lfft = 2 * mapped_lmax; nfft = lfft + 2; mapcols2 = mapcols/2; /* Let's try this since SGI's like odd leading dimensions of the first array in sgemm */ // nlatx=2*(nlat/2)+1; /* make nlatx divisible by 4 on linux systems */ //#ifdef __linux__ if (nlat % 4) nlatx=4*(nlat/4+1); else nlatx=nlat; //#endif DRMS_RecordSet_t *outrecset, *v2hrecset, *h2mrecset; if (tsflag) { real4evenl = (float *)(malloc (nlatx*maxnsn*sizeof(float))); real4oddl = (float *)(malloc (nlatx*maxnsn*sizeof(float))); imag4evenl = (float *)(malloc (nlatx*maxnsn*sizeof(float))); imag4oddl = (float *)(malloc (nlatx*maxnsn*sizeof(float))); outx = (float *)(malloc (maxnsn*2*lchunksize*sizeof(float))); plm = (double *)(malloc ((lmax+1)*nlat*sizeof(double))); saveplm = (double *)(malloc ((lmax+1)*nlat*2*sizeof(double))); latgrid = (double *)(malloc (nlat*sizeof(double))); for (i=0; i= tstart+chunksecs) { if (forceoutput) { nodata=1; goto skip_norecs; } else { fprintf(stderr, "ERROR: no data for timechunk beginning at %s\n", tstartstr); error++; tstart+=chunksecs; continue; } } while (trec < tstart && chunkstat != kRecChunking_NoMoreRecs) { inrec = drms_recordset_fetchnext(drms_env, inrecset, &fetchstat, &chunkstat, NULL); if (inrec != NULL) { trec = drms_getkey_time(inrec, "T_REC", &status); sprint_time(trecstr, trec, "TAI", 0); } } bc=0; nodata=0; mixflag=0; calversunset=1; trecind=(trec-tstart+cadence/2)/cadence; for (irec=0; irec < nrecs && chunkstat != kRecChunking_NoMoreRecs; irec++) { if (trecind > irec) //some inputs were missing { if (forceoutput) { bad[bc++]=irec; continue; } else { fprintf(stderr, "ERROR: some input records missing, T_START = %s, T_REC = %s, irec = %d\n", tstartstr, trecstr, irec); error++; goto continue_outer_loop; } } while (trecind < irec && chunkstat != kRecChunking_NoMoreRecs) //T_REC is duplicated in input { if (forceoutput) { inrec = drms_recordset_fetchnext(drms_env, inrecset, &fetchstat, &chunkstat, NULL); if (inrec != NULL) { trec = drms_getkey_time(inrec, "T_REC", &status); sprint_time(trecstr, trec, "TAI", 0); trecind=(trec-tstart+cadence/2)/cadence; } } else { fprintf(stderr, "ERROR: some input records have duplicate T_REC, T_START = %s, T_REC = %s, irec = %d\n", tstartstr, trecstr, irec); error++; goto continue_outer_loop; } } if (verbflag > 1) { wt2=getwalltime(); ct2=getcputime(&ut2, &st2); printf(" processing record %d\n", irec); } quality=drms_getkey_int(inrec, "QUALITY", &status); if (status != DRMS_SUCCESS || (quality & QUAL_NODATA)) //may want stricter test on quality here { bad[bc++]=irec; if (verbflag > 2) fprintf(stderr, "SKIP: image rejected based on quality: T_REC = %s, quality = %08x\n", trecstr, quality); goto skip; } if (tsflag) { if (calversunset) { calversout=drms_getkey_longlong(inrec, "CALVER64", &status); if (status != DRMS_SUCCESS) calversout = 0; else calversout = fixcalver64(calversout); calversunset=0; for (i=0;i<16;i++) nybblearrout[i]=getbits(calversout,4*i+3,4); } calvers=drms_getkey_longlong(inrec, "CALVER64", &status); if (status != DRMS_SUCCESS) calvers = 0; else calvers = fixcalver64(calvers); for (i=0;i<16;i++) { int nybble=getbits(calvers,4*i+3,4); if (fixflagarr[i]) { if (nybble != nybblearrout[i]) { fprintf(stderr, "ERROR: input data has mixed values for field %d of CALVER64: %d and %d, recnum = %lld, histrecnum = %lld\n", i, nybblearrout[i], nybble, inrec->recnum, histrecnum); error++; goto continue_outer_loop; } } else { if (nybble < nybblearrout[i]) nybblearrout[i]=nybble; } } if (!mixflag && calvers != calversout) mixflag=1; } if (seginflag) segin = drms_segment_lookup(inrec, segnamein); else segin = drms_segment_lookupnum(inrec, 0); if (segin != NULL) inarr = drms_segment_read(segin, usetype, &status); if (segin == NULL || inarr == NULL || status != DRMS_SUCCESS) { fprintf(stderr, "ERROR: problem with input segment or array: status = %d, T_REC = %s, recnum = %lld, histrecnum = %lld\n", status, trecstr, inrec->recnum, histrecnum); return 0; } if (maxmissvals > 0) { int missvals = drms_getkey_int(inrec, "MISSVALS", &status); PARAMETER_ERROR("MISSVALS") if (missvals > maxmissvals) { bad[bc++]=irec; if (verbflag > 1) fprintf(stderr, "SKIP: %d pixels MISSING, max allowed is %d: T_REC = %s, recnum = %lld\n", missvals, maxmissvals, trecstr, inrec->recnum); drms_free_array(inarr); goto skip; } } tobs = drms_getkey_time(inrec, "T_OBS", &status); PARAMETER_ERROR("T_OBS") // MDI keyword was OBS_B0 b0 = drms_getkey_double(inrec, "CRLT_OBS", &status); PARAMETER_ERROR("CRLT_OBS") // MDI keyword was OBS_L0 obsl0 = drms_getkey_double(inrec, "CRLN_OBS", &status); PARAMETER_ERROR("CRLN_OBS") if (p0 == 999.0) { // MDI keyword was SOLAR_P = -(SAT_ROT + INST_ROT) /* satrot = drms_getkey_double(inrec, "SAT_ROT", &status); PARAMETER_ERROR("SAT_ROT") instrot = drms_getkey_double(inrec, "INST_ROT", &status); PARAMETER_ERROR("INST_ROT") p=-(satrot+instrot); */ double crota = drms_getkey_double(inrec, "CROTA2", &status); PARAMETER_ERROR("CROTA2") p=-crota; } else { p = p0; } p = psign * p ; b0 = b0 + ierr * sin((tobs - trefb0) / 31557600. * 2 * PI); p = p + perr - ierr * cos((tobs - trefb0) / 31557600. * 2 * PI); // S_MAJOR, S_MINOR, S_ANGLE, X_SCALE, Y_SCALE were MDI keywords, not used for HMI, but still necessary for GONG data smajor = drms_getkey_double(inrec, "S_MAJOR", &status); ParameterDef(status, "S_MAJOR", 1.0, &smajor, inrec->recnum, 0); sminor = drms_getkey_double(inrec, "S_MINOR", &status); ParameterDef(status, "S_MINOR", 1.0, &sminor, inrec->recnum, 0); sangle = drms_getkey_double(inrec, "S_ANGLE", &status); ParameterDef(status, "S_ANGLE", 0.0, &sangle, inrec->recnum, 0); /* our calculation of CDELTi does not follow WCS conventions. it should be the plate scale at the reference pixel (disk center), but instead we use the average between center and limb. this is taken into account in the calculation of rsun below. */ xscale = drms_getkey_double(inrec, "CDELT1", &status); PARAMETER_ERROR("CDELT1") yscale = drms_getkey_double(inrec, "CDELT2", &status); PARAMETER_ERROR("CDELT2") // use xscale and yscale for the following check, then set to 1.0 for the call to obs2helio if (xscale != yscale) { fprintf(stderr, "ERROR: CDELT1 != CDELT2 not supported, CDELT1 = %f, CDELT2 = %f: T_REC = %s, recnum = %lld \n", xscale, yscale, trecstr, inrec->recnum); drms_free_array(inarr); error++; goto continue_outer_loop; } imagescale=xscale; xscale=1.0; yscale=1.0; /* imagescale = drms_getkey_double(inrec, "IM_SCALE", &status); PARAMETER_ERROR("IM_SCALE") */ if (paramsign != 0) { vsign = paramsign; } else { vsign = drms_getkey_double(inrec, "DATASIGN", &status); ParameterDef(status, "DATASIGN", 1.0, &vsign, inrec->recnum, 1); } if (velocity_correction) { obs_vr = drms_getkey_double(inrec, "OBS_VR", &status); ParameterDef(status, "OBS_VR", 0.0, &obs_vr, inrec->recnum, 1); obs_vw = drms_getkey_double(inrec, "OBS_VW", &status); ParameterDef(status, "OBS_VW", 0.0, &obs_vw, inrec->recnum, 1); obs_vn = drms_getkey_double(inrec, "OBS_VN", &status); ParameterDef(status, "OBS_VN", 0.0, &obs_vn, inrec->recnum, 1); } // MDI keyword was OBS_DIST, in AU obsdist = drms_getkey_double(inrec, "DSUN_OBS", &status) / AU; // note that an incorrect value of 1.49597892e11 has sometimes been used to convert between OBS_DIST and DSUN_OBS when porting data from DSDS to DRMS ParameterDef(status, "OBS_DIST", 1.0, &obsdist, inrec->recnum, 1); if (readrsunref) { rsunref = drms_getkey_double(inrec, "RSUN_REF", &status); ParameterDef(status, "RSUN_REF", RTRUE, &rsunref, inrec->recnum, 1); rtrue=rsunref/AU; } S = rtrue / obsdist; // radians - approx. arcsin(rtrue/obsdist), but don't undo this approximation, because it is assumed in obs2helio rsunobs = drms_getkey_double(inrec, "RSUN_OBS", &status); if (status == DRMS_SUCCESS) rsun = rsunobs/imagescale; //this calculation of rsun assumes approximation of imagescale mentioned in comment above else { rsun = drms_getkey_double(inrec, "R_SUN", &status); if (status != DRMS_SUCCESS) rsun = ARCSECSINRAD * S / sqrt(1.0 - S * S) / imagescale; } if (longitude_shift == 1) { tmearth = tobs+TAU_A*(1.0-obsdist); longshift = (obsl0-refl0)+longrate*(tmearth-tref); // degrees while (longshift > 180.0) longshift-=360.0; while (longshift < -180.0) longshift+=360.0; } else if (longitude_shift == 2) // Shift center to nearest Carrington Degree { longshift = obsl0 - (int)(obsl0); if (longshift > 0.5) longshift -= 1.0; } else if (longitude_shift == 3) // Shift center to nearest tenth of a degree { longshift = (obsl0 * 10 - (int)(obsl0 * 10)) / 10; if (longshift > 0.5) longshift -= 1.0; } else { longshift = 0.0; } mapl0 = obsl0 - longshift; xpixels = inarr->axis[0]; ypixels = inarr->axis[1]; pixels = xpixels * ypixels; // MDI keyword was X0 x0 = drms_getkey_double(inrec, "CRPIX1", &status); ParameterDef(status, "CRPIX1", xpixels / 2, &x0, inrec->recnum, 1); x0 -= 1.0; // MDI keyword was Y0 y0 = drms_getkey_double(inrec, "CRPIX2", &status); ParameterDef(status, "CRPIX2", ypixels / 2, &y0, inrec->recnum, 1); y0 -= 1.0; if (mag_offset) { float *dat = (float *)inarr->data; double bfitzero = drms_getkey_double(inrec, "BFITZERO", &status); PARAMETER_ERROR("BFITZERO") int i; if (!isnan(bfitzero)) { for (i = 0; i < pixels; ++i) { dat[i] -= (float)bfitzero; } } } if (checko) { orientation = drms_getkey_string(inrec, "ORIENT", &status); PARAMETER_ERROR("ORIENT") CheckO(orientation, &vstat); if (vstat != V2HStatus_Success) { fprintf(stderr,"ERROR: illegal ORIENT: T_REC = %s, recnum = %lld\n", trecstr, inrec->recnum); drms_free_array(inarr); free(orientation); error++; goto continue_outer_loop; } } else { orientation = strdup(orientationdef); } if (status = obs2helio((float *)inarr->data, v2hptr, xpixels, ypixels, x0, y0, b0 * RADSINDEG, p * RADSINDEG, S, rsun, rmax, interpolation, mapcols, maprows, longmin_adjusted * RADSINDEG, longinterval * RADSINDEG, longshift * RADSINDEG, sinBdelta, smajor, sminor, sangle * RADSINDEG, xscale, yscale, orientation, mag_correction, velocity_correction, obs_vr, obs_vw, obs_vn, vsign, NaN_beyond_rmax, carrStretch, &distP, diffrotA, diffrotB, diffrotC, NULL, 0)) { fprintf(stderr, "ERROR: failure in obs2helio: status = %d, T_REC = %s, recnum = %lld\n", status, trecstr, inrec->recnum); drms_free_array(inarr); free(orientation); error++; goto continue_outer_loop; } drms_free_array(inarr); free(orientation); if (status = apodize(v2hptr, b0 * RADSINDEG, mapcols, maprows, longmin_adjusted * RADSINDEG, longinterval * RADSINDEG, sinBdelta, apodization, apinner, apwidth, apel, apx, apy)) { fprintf(stderr, "ERROR: failure in apodize: status = %d, T_REC = %s, recnum = %lld\n", status, trecstr, inrec->recnum); error++; goto continue_outer_loop; } if (v2hflag) { // outrec = drms_create_record(drms_env, v2hout, lifetime, &status); outrec=v2hrecset->records[iv2hrec++]; drms_copykeys(outrec, inrec, 0, kDRMS_KeyClass_Explicit); DRMS_Link_t *histlink = hcon_lookup_lower(&outrec->links, histlinkname); DRMS_Link_t *srclink = hcon_lookup_lower(&outrec->links, srclinkname); if (histlink != NULL) drms_setlink_static(outrec, histlinkname, histrecnum); if (srclink != NULL) drms_setlink_static(outrec, srclinkname, inrec->recnum); if (segoutflag) segout = drms_segment_lookup(outrec, segnameout); else segout = drms_segment_lookupnum(outrec, 0); length[0]=mapcols; length[1]=maprows; outarr = drms_array_create(usetype, 2, length, v2hptr, &status); drms_setkey_int(outrec, "TOTVALS", maprows*mapcols); set_statistics(segout, outarr, 1); outarr->bzero=segout->bzero; outarr->bscale=segout->bscale; status=drms_segment_write(segout, outarr, 0); free(outarr); if (status != DRMS_SUCCESS) { fprintf(stderr, "ERROR: problem writing output segment: status = %d, T_REC = %s, input recnum = %lld, histrecnum = %lld\n", status, trecstr, inrec->recnum, histrecnum); return 0; } // drms_copykey(outrec, inrec, "T_REC"); drms_setkey_int(outrec, "QUALITY", quality); drms_setkey_int(outrec, "MAPMMAX", mapped_lmax); drms_setkey_int(outrec, "SINBDIVS", sinb_divisions); drms_setkey_float(outrec, "CRPIX1", mapcols/2.0 + 0.5); drms_setkey_float(outrec, "CRVAL1", mapl0); drms_setkey_float(outrec, "CROTA1", 0.0); drms_setkey_float(outrec, "CDELT1", longinterval); drms_setkey_float(outrec, "CRPIX2", maprows/2.0 + 0.5); drms_setkey_float(outrec, "CRVAL2", 0.0); drms_setkey_float(outrec, "CROTA2", 0.0); drms_setkey_float(outrec, "CDELT2", sinBdelta); drms_setkey_string(outrec, "CTYPE1", "CRLN_CEA"); drms_setkey_string(outrec, "CTYPE2", "CRLT_CEA"); drms_setkey_string(outrec, "CUNIT1", "deg"); drms_setkey_string(outrec, "CUNIT2", "sinlat"); // set keywords for magnetic pipeline drms_setkey_float(outrec, "MAPRMAX", rmax); drms_setkey_float(outrec, "MAPBMAX", bmax); drms_setkey_float(outrec, "MAPLGMAX", longmax_adjusted); drms_setkey_float(outrec, "MAPLGMIN", longmin_adjusted); drms_setkey_int(outrec, "INTERPO", interpolation); drms_setkey_int(outrec, "LGSHIFT", longitude_shift); drms_setkey_int(outrec, "MCORLEV", mag_correction); drms_setkey_int(outrec, "MOFFSET", mag_offset); drms_setkey_int(outrec, "CARSTRCH", carrStretch); drms_setkey_float(outrec, "DIFROT_A", diffrotA); drms_setkey_float(outrec, "DIFROT_B", diffrotB); drms_setkey_float(outrec, "DIFROT_C", diffrotC); dsignout=vsign*drms_getkey_double(inrec, "DATASIGN", &status); if (status != DRMS_SUCCESS) dsignout=vsign; dsignout/=fabs(dsignout); drms_setkey_int(outrec, "DATASIGN", (int)dsignout); tnow = (double)time(NULL); tnow += UNIX_epoch; drms_setkey_time(outrec, "DATE", tnow); // drms_close_record(outrec, DRMS_INSERT_RECORD); } if (verbflag > 1) { wt=getwalltime(); ct=getcputime(&ut, &st); fprintf(stdout, " remap done, %.2f ms wall time, %.2f ms cpu time\n", wt-wt2, ct-ct2); } if (!h2mflag && !tsflag) goto skip; inp=v2hptr; outp=h2mptr; mean = 0.0; if (subtract_mean) /* get mean of entire remapped image */ { nmean = 0; ip = inp; for (row=0; rowrecords[ih2mrec++]; drms_copykeys(outrec, inrec, 0, kDRMS_KeyClass_Explicit); DRMS_Link_t *histlink = hcon_lookup_lower(&outrec->links, histlinkname); DRMS_Link_t *srclink = hcon_lookup_lower(&outrec->links, srclinkname); if (histlink != NULL) drms_setlink_static(outrec, histlinkname, histrecnum); if (srclink != NULL) drms_setlink_static(outrec, srclinkname, inrec->recnum); if (segoutflag) segout = drms_segment_lookup(outrec, segnameout); else segout = drms_segment_lookupnum(outrec, 0); length[0]=maprows; length[1]=nout; outarr = drms_array_create(usetype, 2, length, h2mptr, &status); drms_setkey_int(outrec, "TOTVALS", maprows*nout); set_statistics(segout, outarr, 1); outarr->bzero=segout->bzero; outarr->bscale=segout->bscale; status=drms_segment_write(segout, outarr, 0); free(outarr); if (status != DRMS_SUCCESS) { fprintf(stderr, "ERROR: problem writing output segment: status = %d, T_REC = %s, input recnum = %lld, histrecnum = %lld\n", status, trecstr, inrec->recnum, histrecnum); return 0; } // drms_copykey(outrec, inrec, "T_REC"); drms_setkey_int(outrec, "QUALITY", quality); drms_setkey_int(outrec, "MAPMMAX", mapped_lmax); drms_setkey_int(outrec, "SINBDIVS", sinb_divisions); drms_setkey_int(outrec, "LMAX", lmax); drms_setkey_double(outrec, "CRPIX1", maprows/2.0 + 0.5); drms_setkey_double(outrec, "CRVAL1", 0.0); drms_setkey_double(outrec, "CROTA1", 0.0); drms_setkey_double(outrec, "CDELT1", sinBdelta); drms_setkey_double(outrec, "CRPIX2", 1.0); drms_setkey_double(outrec, "CRVAL2", 0.0); drms_setkey_double(outrec, "CROTA2", 0.0); drms_setkey_double(outrec, "CDELT2", 1.0); drms_setkey_string(outrec, "CTYPE1", "CRLT_CEA"); drms_setkey_string(outrec, "CTYPE2", "CRLN_FFT"); drms_setkey_string(outrec, "CUNIT1", "rad"); drms_setkey_string(outrec, "CUNIT2", "m"); tnow = (double)time(NULL); tnow += UNIX_epoch; drms_setkey_time(outrec, "DATE", tnow); // drms_close_record(outrec, DRMS_INSERT_RECORD); } if (verbflag > 1) { wt2=getwalltime(); ct2=getcputime(&ut2, &st2); fprintf(stdout, " fft and transpose done, %.2f ms wall time, %.2f ms cpu time\n", wt2-wt, ct2-ct); } if (!tsflag) goto skip; inptr=h2mptr; imageoffset = imagesize * irec; for (mx = 0; mx < 2*msize; mx++) /* for each m, re and im */ { moffset = mx * maprows; mptr = inptr + moffset; for (latx = 0; latx < nlat; latx++) { poslatx = nlat + latx; neglatx = nlat - 1 - latx; evenpart[latx] = mptr[poslatx] + mptr[neglatx]; oddpart[latx] = mptr[poslatx] - mptr[neglatx]; } workptr = folded + imageoffset + moffset; scopy_ (&nlat, evenpart, &increment1, workptr, &increment1); workptr += nlat; scopy_ (&nlat, oddpart, &increment1, workptr, &increment1); } skip: inrec = drms_recordset_fetchnext(drms_env, inrecset, &fetchstat, &chunkstat, NULL); if (inrec != NULL) { trec = drms_getkey_time(inrec, "T_REC", &status); PARAMETER_ERROR("T_REC") trecind=(trec-tstart+cadence/2)/cadence; sprint_time(trecstr, trec, "TAI", 0); } } /* end loop on each input image for this timechunk */ if (verbflag) printf(" number of bad images = %d\n", bc); if (!tsflag) goto continue_outer_loop; //needed if recordset does not extend to end of a timechunk while (irec < nrecs) { bad[bc++]=irec; irec++; } if (bc == nrecs) { nodata=1; } else { while (bc > 0) { imageoffset=imagesize*bad[--bc]; for (i=0;i 1) { wt3=getwalltime(); ct3=getcputime(&ut3, &st3); printf(" processing lchunk %d, lmin = %d, lmax = %d\n", lchunk, lfirst, llast); } // outrec = drms_create_record(drms_env, outseries, lifetime, &status); outrec=outrecset->records[irecout++]; /* if (status != DRMS_SUCCESS || outrec == NULL) { fprintf(stderr,"ERROR: unable to open record in output dataseries %s, status = %d, histrecnum = %lld\n", outseries, status, histrecnum); return 0; } */ if (histlink != NULL) drms_setlink_static(outrec, histlinkname, histrecnum); if (nodata) goto skip_nodata; /* now the size of the output array is known */ length[0]=2*nrecs; /* accomodate re & im parts for each sn */ length[1]=(ilast-ifirst+1); /* for each l & m, lfirst <= l <= llast */ outarr = drms_array_create(usetype, 2, length, NULL, &status); if (segoutflag) segout = drms_segment_lookup(outrec, segnameout); else segout = drms_segment_lookupnum(outrec, 0); if (segout == NULL || outarr == NULL || status != DRMS_SUCCESS) { fprintf(stderr,"ERROR: problem with output segment or data array: lfirst = %d, llast = %d, length = [%d, %d], status = %d, iset = %d, T_START= %s, histrecnum = %lld", lfirst, llast, length[0], length[1], status, iset, tstartstr, histrecnum); return 0; } outptr = (float *)(outarr->data); /* loop on each m */ for (m = 0; m <= llast; m++) { modd = is_odd(m); meven = !modd; lstart = maxval(lfirst,m); /* no l can be smaller than this m */ /* set up masks (plm's) for this m and chunk in l */ if ((lstart-1) == ldone) { /* get saved plms if any */ if ((lstart - 2) >= m) for (latx = 0; latx < nlat; latx++) plm[(lstart-2)*nlat + latx] = saveplm[m*nlat + latx]; if ((lstart - 1) >= m) for (latx = 0; latx < nlat; latx++) plm[(lstart-1)*nlat + latx] = saveplm[msize*nlat + m*nlat + latx]; /* then set up the current chunk */ // setplm_ (&lstart, &llast, &m, &nlat, indx, latgrid, &nlat, plm); setplm2(lstart, llast, m, nlat, indx, latgrid, nlat, plm, NULL); } else { /* This fixes the lmin != 0 problem */ // setplm_ (&m, &llast, &m, &nlat, indx, latgrid, &nlat, plm); setplm2(m, llast, m, nlat, indx, latgrid, nlat, plm, NULL); } /* save plm's for next chunk */ if ((llast-1) >= m) for (latx = 0; latx < nlat; latx++) saveplm[m*nlat + latx] = plm[(llast - 1)*nlat + latx]; for (latx = 0; latx < nlat; latx++) saveplm[msize*nlat + m*nlat + latx] = plm[llast*nlat + latx]; ldone=llast; /* copy plm's into masks */ /* note that this converts from double to single precision */ /* the test prevents underflows which gobble CPU time */ /* Hmmm... looks like if statement is not needed. Weird... for (l = lstart; l <= llast; l++) { moffset = l * nlat; for (latx = 0; latx < nlat; latx++) { plmptr = plm + moffset + latx; if (is_very_small (*plmptr)) masks [(l-lstart)*nlat + latx] = 0.0; else masks [(l-lstart)*nlat + latx] = *plmptr; } plmptr = plm + moffset; maskptr = masks+(l-lstart)*nlat; dscopy_(&nlat,plmptr,maskptr); } */ plmptr=plm+nlat*lstart; maskptr=masks; latx=nlat*(llast-lstart+1); // dscopy_(&latx,plmptr,maskptr); int ilatx; for (ilatx=0;ilatxbzero=segout->bzero; outarr->bscale=segout->bscale; status=drms_segment_write(segout, outarr, 0); drms_free_array(outarr); nsegments++; if (status != DRMS_SUCCESS) { fprintf(stderr, "ERROR: problem writing output segment: status = %d, T_START = %s, LMIN = %d, LMAX = %d, histrecnum = %lld\n", status, tstartstr, lfirst, llast, histrecnum); return 0; } skip_nodata: drms_setkey_int(outrec, "LMIN", lfirst); drms_setkey_int(outrec, "LMAX", llast); drms_setkey_time(outrec, "T_START", tstart); drms_setkey_time(outrec, "T_STOP", tstart+chunksecs); drms_setkey_time(outrec, "T_OBS", tstart+chunksecs/2); drms_setkey_time(outrec, "DATE__OBS", tstart); drms_setkey_string(outrec, "TAG", tag); if (verflag) drms_setkey_string(outrec, "VERSION", version); for (i=0;i<16;i++) setbits(calversout,4*i+3,4,nybblearrout[i]); drms_setkey_longlong(outrec, "CALVER64", calversout); if (nodata) drms_setkey_int(outrec, "QUALITY", QUAL_NODATA); else if (mixflag) drms_setkey_int(outrec, "QUALITY", QUAL_MIXEDCALVER); else drms_setkey_int(outrec, "QUALITY", 0); // these could be constant, but set them just in case drms_setkey_int(outrec, "MAPMMAX", mapped_lmax); drms_setkey_int(outrec, "SINBDIVS", sinb_divisions); drms_setkey_float(outrec, "T_STEP", cadence); ndt=chunksecs/cadence; drms_setkey_int(outrec, "NDT", ndt); tnow = (double)time(NULL); tnow += UNIX_epoch; drms_setkey_time(outrec, "DATE", tnow); // drms_close_record(outrec, DRMS_INSERT_RECORD); nrecords++; if (verbflag > 1) { wt=getwalltime(); ct=getcputime(&ut, &st); fprintf(stdout, " %.2f ms wall time, %.2f ms cpu time\n", wt-wt3, ct-ct3); } } /* end loop on each chunk of l's */ if (verbflag) { wt1=getwalltime(); ct1=getcputime(&ut1, &st1); fprintf(stdout, "SHT of timechunk %d complete: %.2f ms wall time, %.2f ms cpu time\n", iset, wt1-wt2, ct1-ct2); } continue_outer_loop: tstart+=chunksecs; } /* end loop on each time chunk */ if (chunkstat != kRecChunking_LastInRS && chunkstat != kRecChunking_NoMoreRecs) fprintf(stderr, "WARNING: input records remain after last output record: chunkstat = %d\n", (int)chunkstat); drms_close_records(inrecset, DRMS_FREE_RECORD); if (tsflag) drms_close_records(outrecset, DRMS_INSERT_RECORD); if (v2hflag) drms_close_records(v2hrecset, DRMS_INSERT_RECORD); if (h2mflag) drms_close_records(h2mrecset, DRMS_INSERT_RECORD); wt=getwalltime(); ct=getcputime(&ut, &st); if (verbflag && tsflag) { printf("number of records created = %d\n", nrecords); printf("number of segments created = %d\n", nsegments); } if (verbflag) { fprintf(stdout, "total time spent: %.2f ms wall time, %.2f ms cpu time\n", wt-wt0, ct-ct0); } if (!error) printf("module %s successful completion\n", cmdparams.argv[0]); else printf("module %s failed to produce %d timechunks: histrecnum = %lld\n", cmdparams.argv[0], error, histrecnum); return 0; }