(file) Return to jv2ts.c CVS log (file) (dir) Up to [Development] / JSOC / proj / globalhs / apps

   1 tplarson 1.4 /*  this JSOC module is a combination of 3 SOI modules: v2helio, helio2mlat, qdotprod
   2 tplarson 1.1  *  ported by Tim Larson
   3               *  removes check on mapbmin, mapbmax, and maprows, these keywords are no longer carried
   4               */
   5              
   6              /*
   7 tplarson 1.9  *  v2helio.c                            ~soi/(version)/src/modules/v2helio.c
   8               *
   9               *  This module interpolates CCD velocity data to estimate values that
  10               *    would be obtained at specified equal increments of heliographic 
  11               *    longitude and sine of latitude.  Apodization and corrections for
  12               *    solar rotation and limbshift are included. 
  13               *
  14               *  Responsible:  Kay Leibrand                   KLeibrand@solar.Stanford.EDU
  15               *
  16               *  Bugs:
  17               *    This module is under development.  Look for ??? in comments.
  18               *
  19               *  Planned updates:
  20               *    Decide when and where and if default values should be used.
  21               *
  22               */
  23              
  24              /*
  25               *  helio2mlat.c                     ~soi/(version)/src/modules/helio2mlat.c
  26               *
  27               *  Description:
  28 tplarson 1.9  *     Adapted by Kay Leibrand from pipeLNU shtfft
  29               *     fft by map_rows.  Use FORTRAN library Cmlib for float version.
  30               *     extends data to 360 degrees prior to transform but only saves
  31               *     cols up to lmax.  Performs transpose needed prior to dotprod.
  32               *
  33               *  Responsible:  Kay Leibrand                   KLeibrand@solar.Stanford.EDU
  34               *
  35               *  Bugs:
  36               *    This module is under development.  Look for ??? in comments.
  37               *
  38               *  Planned updates:
  39               *    Restructure to use functions?
  40               *    Refine parameter definitions and names to be consistent with
  41               *       new keywords and ancillary data flow.
  42               *    Fix phase
  43               *
  44               */
  45              
  46              /*
  47 tplarson 1.1  *  qdotprod.c                     ~soi/(version)/src/modules/qdotprod.c
  48               *
  49               *  Description:
  50               *    Conversion of Jesper Schou's FORTRAN q(uick)dotprod to C 
  51               *    from file ~schou/testdot/testdot4c.f 
  52               *    uses FORTRAN functions from blas library
  53               *    contains optimizations, calculates masks, allows "chunking" in l 
  54               *
  55               *  Responsible:  Kay Leibrand                   KLeibrand@solar.Stanford.EDU
  56               *
  57               *  Bugs:
  58               *    Inadequate checks for consistency between data specifications, 
  59               *      i.e. dataset names, and LMIN, LMAX, LCHUNK parameters.
  60               *    This module is under development.  Look for ??? and TBD in comments.
  61               *    Normalization in plm's is different from PHS pipeLNU
  62               *
  63               *  Planned updates:
  64               *    Fix known bugs. 
  65               *    Use a consistent pointer style, i.e. pointer arith vs [] 
  66               *    Restructure to use functions.
  67               *    Refine parameter definitions and names to be consistent with
  68 tplarson 1.1  *       new keywords and ancillary data flow.
  69               *
  70               *  Revision history is at end of file.
  71               */
  72              
  73              /* Normalization of the resulting time-series when norm != 0:
  74              
  75                Let the observed surface behaviour of an oscillation be given by 
  76                Re(exp(-i\omega t) Y_l^m (\theta,\phi)) with (Y_l^m)^2 normalized
  77                to have an average of 1 over the unit sphere (this is 4\pi times
  78                the usual definition where the integral is 1). Assume that the
  79                whole (4\pi) Sun is observed with no velocity projection factor.
  80                Then the resulting time series is given by exp(-i\omega t).
  81              
  82                This is equivalent to preserving the rms value of the real parts
  83                of the oscillations.
  84              
  85                And maybe I got the implementation straight.
  86              
  87              */
  88              
  89 tplarson 1.1 #include <stdio.h>
  90              #include <math.h>
  91              #include <stdlib.h>
  92              #include <time.h>
  93              #include <sys/time.h>
  94              #include <sys/resource.h>
  95              #include <fftw3.h>
  96              #include "jsoc_main.h"
  97 tplarson 1.9 #include "fstats.h"
  98 tplarson 1.1 #include "drms_dsdsapi.h"
  99              #include "errlog.h"
 100 tplarson 1.21 #include "projection.h"
 101 tplarson 1.23 #include "atoinc.h"
 102 tplarson 1.1  
 103               #define ARRLENGTH(ARR)  (sizeof(ARR)/sizeof(ARR[0]))
 104               #define PI              (M_PI)
 105               
 106               #define absval(x)		(((x) < 0) ? (-(x)) : (x))
 107               #define minval(x,y)		(((x) < (y)) ? (x) : (y))
 108               #define maxval(x,y)		(((x) < (y)) ? (y) : (x))
 109               #define very_small		(1.0e-30)
 110               #define is_very_small(x)	(absval(x) < very_small)
 111               #define is_even(x) 		(!((x)%2))
 112               #define is_odd(x) 		((x)%2)
 113               
 114               #define RADSINDEG 	(PI/180)
 115               #define ARCSECSINRAD 	(3600*180/PI)
 116               #define DAYSINYEAR	(365.2425)
 117               #define SECSINDAY	(86400)
 118               #define TAU_A           (499.004783806) // light travel time in seconds, = 1 AU/c
 119               //#define TAU_A		(499.004782)	// this value used in old v2helio
 120               #define TCARR		(25.38)		// days
 121               #define RTRUE		(6.96000000e8)	// meters
 122               #define AU		(149597870691)	// meters/au
 123 tplarson 1.1  //#define AU		(1.49597870e11)	// this value used in old v2helio
 124               
 125 tplarson 1.20 #define QUAL_NODATA	 (0x80000000)
 126               #define QUAL_MIXEDCALVER (0x00000001)
 127 tplarson 1.1  #define kNOTSPECIFIED  "not specified"
 128               
 129               char *module_name = "jv2ts";
 130 tplarson 1.24 char *cvsinfo_jv2ts = "cvsinfo: $Header: /home/cvsuser/cvsroot/JSOC/proj/globalhs/apps/jv2ts.c,v 1.23 2013/07/02 20:32:03 tplarson Exp $";
 131 tplarson 1.1  
 132               ModuleArgs_t module_args[] = 
 133               {
 134               // these inputs are common to all modules
 135                  {ARG_STRING, "in",           NULL,           "input data records"},
 136 tplarson 1.9     {ARG_STRING, "tsout",        kNOTSPECIFIED,  "output data series"},
 137 tplarson 1.1     {ARG_STRING, "segin",        kNOTSPECIFIED,  "input data segment"},
 138                  {ARG_STRING, "segout",       kNOTSPECIFIED,  "output data segment"},
 139 tplarson 1.21    {ARG_STRING, "histlink",     "HISTORY",      "name of link to ancillary dataseries for processing metadata. specify \"none\" to suppress warning messages."},
 140 tplarson 1.1     {ARG_STRING, "srclink",      "SRCDATA",      "name of link to source data"}, // used only for jv2helio and jhelio2mlat output
 141                  {ARG_STRING, "v2hout",       kNOTSPECIFIED,  "output data series for jv2helio"},
 142                  {ARG_STRING, "h2mout",       kNOTSPECIFIED,  "output data series for jhelio2mlat"},
 143                  {ARG_INT,    "PERM",         "1",            "set to 0 for transient records, nonzero for permanent records"},
 144 tplarson 1.8     {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"},
 145                  {ARG_INT,    "FORCEOUTPUT",  "0",            "option to specify behavior on missing inputs; 0 gives an error on missing or duplicate inputs, >0 makes outputs regardless"},
 146                  {ARG_STRING, "TAG",          "none",         "this parameter sets a keyword of the same name to the same value, usually used as an additional primekey"},
 147 tplarson 1.23    {ARG_STRING, "VERSION",      kNOTSPECIFIED,  "this parameter sets a keyword of the same name to the same value, useful for selecting obsolete records"},
 148 tplarson 1.20    {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."},
 149 tplarson 1.1  // these are from jqdotprod
 150                  {ARG_INT,    "LMIN",         "0",            "minimum l in output"},
 151               //   {ARG_INT,    "LMAX",         "0",            "maximum l in output, take from input if 0"},   /* if 0, default is LMAX of in_sds */
 152                  {ARG_INT,    "LCHUNK",       "0",            "increment in l on output, default is lmax+1"},   /* if 0, is LMAX+1 */ 
 153                  {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 */ 
 154 tplarson 1.8     {ARG_TIME,   "TSTART",       NULL,           "start time of first output record"},
 155                  {ARG_STRING, "TTOTAL",       NULL,           "total length of time in output"},
 156 tplarson 1.1     {ARG_STRING, "TCHUNK",       kNOTSPECIFIED,  "length of output timeseries"},
 157               // these are from jhelio2mlat
 158                  {ARG_INT,    "LMAX",         "300",       "maximum l (maximum m) in the output, cannot be greater than MAPMMAX", NULL},
 159                  {ARG_INT,    "SUBMEAN",      "0",         "nonzero subtracts mean of input image", NULL},
 160                  {ARG_INT,    "NORMLIZE",     "0",         "nonzero multiplies by sqrt((fraction nonmissing)/2) for each row", NULL},
 161                  {ARG_INT,    "CENTLONG",     "1",         "nonzero centers the longitude Fourier transform on the center of the remapped image", NULL},
 162 tplarson 1.10    {ARG_INT,    "ZEROMISS",     "0",         "zero sets any row containing a NaN to DRMS_MISSING", NULL},
 163 tplarson 1.1     {ARG_INT,    "LGAPOD",       "0",         "nonzero apodizes in longitude", NULL},
 164                  {ARG_DOUBLE, "LGAPMIN",      "60.0",      "start of longitude apodization, degrees", NULL},
 165                  {ARG_DOUBLE, "LGAPWIDT",     "10.0",      "width of longitude apodization, degrees", NULL},
 166               // these are from jv2helio
 167                  {ARG_INT,     "MAPMMAX",     "1536",      "determines mapcols", ""},	/* determines mapcols, default value is 3*512 */
 168                  {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) */
 169                  {ARG_FLOAT,   "MAPRMAX",     "0.95",      "maximum image radius", ""},
 170 tplarson 1.24    {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 */   
 171 tplarson 1.1     {ARG_FLOAT,   "MAPLGMAX",    "72.0",      "longitude maximum, degrees", ""},	/* degrees */    
 172                  {ARG_FLOAT,   "MAPLGMIN",    "-72.0",     "longitude minimum, degrees", ""},
 173                  {ARG_FLOAT,   "MAPBMAX",     "72.0",      "latitude maximum, degrees, also used for minimum", ""},  
 174                  {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 */
 175                  {ARG_TIME,    "REF_T0",      "1987.01.03_17:31:12_TAI", "reference time for computing fixed rate longitude shift", ""},
 176                  {ARG_FLOAT,   "REF_L0",      "0.0",       "reference longitude for computing fixed rate longitude shift ", ""},
 177                  {ARG_FLOAT,   "SOLAR_P",     "999.0",     "P-angle; if unset, taken from keywords", ""},	/* can't use D_MISSING here */
 178                  {ARG_FLOAT,   "PSIGN",       "1.0",       "sign of SOLAR_P", ""},	/* Sign of P. For MWO data. */
 179                  {ARG_FLOAT,   "PERR",        "0.0",       "fixed P-angle error, likely -0.22", ""},	/* Fixed P-angle error. Maybe -0.22. */
 180                  {ARG_FLOAT,   "IERR",        "0.0",       "error in Carrington inclination, likely -0.10", ""},	/* Error in Carrington inclination. Maybe -0.10. */
 181                  {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", ""},
 182                  {ARG_INT,     "INTERPO",     "1",         "option for interpolation: 0=bilinear; 1=cubic convolution", ""},	/* 2 methods - see soi_fun.h */
 183                  {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 */
 184                  {ARG_FLOAT,   "APINNER",     "0.90",      "start of apodization in fractional image radius", ""},	/* start of apodization */
 185                  {ARG_FLOAT,   "APWIDTH",     "0.05",      "width of apodization in fractional image radius", ""},	/* width of apodization */
 186                  {ARG_INT,     "APEL",        "0",         "set to nonzero for elliptical apodization described by APX and APY", ""},	/* do elliptical apodization described by apx and apy */
 187                  {ARG_FLOAT,   "APX",         "1.00",      "divide the x position by this before applying apodization", ""},	/* divide the x position by this before applying apodization */
 188                  {ARG_FLOAT,   "APY",         "1.00",      "divide the y position by this before applying apodization", ""},	/* divide the y position by this before applying apodization */
 189                  {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*/
 190 tplarson 1.24    {ARG_INT,     "MCORLEV",     "0",         "option for magnetic correction: 0=none; 1=line of sight; 2=radial", ""}, 	/* 2 levels - see soi_fun.h*/
 191 tplarson 1.1     {ARG_INT,     "MOFFSETFLAG", "0",         "set to nonzero to get BFITZERO from input record and subtract from data before interpolating", ""}, 	/* 1=apply BFITZERO correction*/
 192                  {ARG_FLOAT,   "OUTSCALE",    "1.0",       "bscale to use for output", ""},    /* scale for output */
 193                  {ARG_FLOAT,   "OUTBIAS",     "0.0",       "bzero to use for output", ""},    /* bias for scaled output */
 194                  {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 */
 195                  {ARG_FLOAT,   "CUBIC",       "7.06E-9",   "cubic distortion in fd units", ""}, /* Cubic distortion in FD units */
 196                  {ARG_FLOAT,   "TILTALPHA",   "2.59",      "tilt of CCD, degrees", ""}, /* TILT of CCD in degrees */
 197                  {ARG_FLOAT,   "TILTBETA",    "56.0",      "direction of CCD tilt, degrees", ""}, /* Direction of TILT in degrees */
 198                  {ARG_FLOAT,   "TILTFEFF",    "12972.629", "effective focal length", ""}, /* Effective focal length */
 199                  {ARG_INT,     "OFLAG",       "0",         "set to nonzero to force reading orientation from keyword, otherwise \"SESW\" is assumed)", ""},  /* Non 0 skips checko (SESW assumed) */
 200                  {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*/
 201                  {ARG_INT,     "MAXMISSVALS", "0",         "if >0, this becomes threshold on MISSVALS from keyword", ""},  /* max. allowed MISSING pixels */
 202                  {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 */
 203                  {ARG_FLOAT,   "DIFROT_A",    "13.562",    "A coefficient in differential rotation adjustment (offset)", ""}, /* A coefficient in diff rot adj (offset) */
 204                  {ARG_FLOAT,   "DIFROT_B",    "-2.04",     "B coefficient (to sin(lat) ^ 2)", ""},  /* B coefficient (to sin(lat) ^ 2) */
 205                  {ARG_FLOAT,   "DIFROT_C",    "-1.4875",   "C coefficient (to sin(lat) ^ 4)", ""},  /* C coefficient (to sin(lat) ^ 4) */
 206               
 207                  {ARG_END}
 208               };
 209               
 210               #include "saveparm.c"
 211               #include "timing.c"
 212 tplarson 1.8  #include "set_history.c"
 213 tplarson 1.18 #include "calversfunctions.c"
 214 tplarson 1.1  
 215 tplarson 1.21 int SetDistort(int dist, double cubic, double alpha, double beta, double feff, LIBPROJECTION_Dist_t *dOut);
 216 tplarson 1.19 
 217 tplarson 1.21 int obs2helio(float *V, float *U, int xpixels, int ypixels, double x0, double y0, double BZero, double P,
 218 tplarson 1.19               double   S, double rsun, double Rmax, int	interpolation, int cols, int rows, double Lmin,
 219                             double Ldelta, double Ladjust, double sinBdelta, double smajor, double sminor, double sangle,
 220                             double xscale, double yscale, const char *orientation, int mag_correction, int velocity_correction,
 221                             double obs_vr, double obs_vw, double obs_vn, double vsign, int NaN_beyond_rmax, int carrStretch,
 222 tplarson 1.21               const LIBPROJECTION_Dist_t *distpars, float diffrotA, float diffrotB, float diffrotC, 
 223                             LIBPROJECTION_RotRate_t *rRates, int size);
 224 tplarson 1.19 
 225               int apodize(float *data, double b0, int cols, int rows, double Lmin, double Ldelta, double sinBdelta, 
 226                           int apodlevel, double apinner, double apwidth, int apel, double apx, double apy);
 227               
 228               void setplm2(int lmin,int lmax,int m,long nx,int *indx,double *x,long nplm,double *plm,double *dplm);
 229               
 230 tplarson 1.21 //char *getshtversion(void);
 231 tplarson 1.19 
 232 arta     1.3  /* forward decls for fortran functions */
 233               void scopy_(int *, float *, int *, float *, int *);
 234               void setplm_(int *, int *, int *, int *, int *, double *, int *, double *);
 235               void sgemm_(); /* give up */
 236               
 237 tplarson 1.1  typedef enum
 238               {
 239                  V2HStatus_Success,
 240                  V2HStatus_MissingParameter,
 241                  V2HStatus_IllegalTimeFormat,
 242                  V2HStatus_TimeConvFailed,
 243                  V2HStatus_Unimplemented,
 244                  V2HStatus_IllegalOrientation
 245               } V2HStatus_t;
 246               
 247               static void CheckO(const char *orientation, V2HStatus_t *stat)
 248               {
 249                  /* check for legal orientation string */
 250                  static char o[16];
 251                  char *c = o;
 252               
 253                  if(!orientation)
 254                  {
 255                     *stat = V2HStatus_MissingParameter;
 256                  } 
 257                  else if (4 != sscanf(orientation, "%[NS]%[EW]%[NS]%[EW]", c++, c++, c++, c++))
 258 tplarson 1.1     {
 259                     *stat = V2HStatus_IllegalOrientation;
 260                  }
 261                  else if ((o[0] == o[2]) && (o[1] == o[3]))
 262                  { 
 263                     *stat = V2HStatus_IllegalOrientation;
 264                  }
 265                  else if ((o[0] !=o [2]) && (o[1] != o[3])) 
 266                  {
 267                     *stat = V2HStatus_IllegalOrientation;
 268                  }
 269                  else 
 270                  {
 271                     *stat = V2HStatus_Success;   
 272                  }
 273               }
 274               
 275               static inline void ParameterDef(int status, 
 276               				char *pname, 
 277               				double defaultp, 
 278               				double *p, 
 279 tplarson 1.8  				long long recnum,
 280 tplarson 1.1                                  int verbflag)
 281               {
 282                  /* logs warning and sets parameter to default value */
 283                  if (status != 0)
 284                  {
 285                     *p = defaultp;
 286                     if (verbflag)
 287 tplarson 1.8           fprintf(stderr, "WARNING: default value %g used for %s, status = %d, recnum = %lld\n", defaultp, pname, status, recnum);
 288 tplarson 1.1     }
 289               }
 290               
 291               #define PARAMETER_ERROR(PNAME) \
 292               if (status != DRMS_SUCCESS) \
 293               { \
 294 tplarson 1.8    fprintf(stderr, "ERROR: problem with required keyword %s, status = %d, T_REC = %s, recnum = %lld, histrecnum = %lld\n", PNAME, status, trecstr, inrec->recnum, histrecnum); \
 295 tplarson 1.1    drms_free_array(inarr); \
 296 tplarson 1.8    return 0; \
 297 tplarson 1.1  }
 298               
 299               
 300               int DoIt(void)
 301               { 
 302                 int newstat=0;
 303                 DRMS_RecChunking_t chunkstat = kRecChunking_None;
 304                 int fetchstat = DRMS_SUCCESS;
 305                 int status = DRMS_SUCCESS;
 306 tplarson 1.8    char *inrecquery = NULL;
 307 tplarson 1.1    char *outseries = NULL;
 308                 char *segnamein = NULL;
 309                 char *segnameout = NULL;
 310 tplarson 1.8    DRMS_RecordSet_t *inrecset = NULL;
 311 tplarson 1.1    DRMS_Record_t *inrec = NULL;
 312                 DRMS_Record_t *outrec = NULL;
 313                 DRMS_Segment_t *segin = NULL;
 314                 DRMS_Segment_t *segout = NULL;
 315                 DRMS_Array_t *inarr = NULL;
 316                 DRMS_Array_t *outarr = NULL;
 317                 DRMS_Type_t usetype = DRMS_TYPE_FLOAT;
 318                 DRMS_RecLifetime_t lifetime;
 319                 long long histrecnum=-1;
 320                 int length[2];
 321               
 322                 double wt0, wt1, wt2, wt3, wt;
 323                 double ut0, ut1, ut2, ut3, ut;
 324                 double st0, st1, st2, st3, st;
 325                 double ct0, ct1, ct2, ct3, ct;
 326               
 327                 TIME trec, tnow, UNIX_epoch = -220924792.000; /* 1970.01.01_00:00:00_UTC */
 328                 char trecstr[100], tstartstr[100];
 329               
 330 tplarson 1.6    int quality;
 331 tplarson 1.1  
 332                 float *v2hptr, *h2mptr;
 333               
 334               // from jqdotprod, norm changed to normflag
 335                 float *oddpart, *evenpart, *inptr, *workptr, *mptr, *outptr;
 336                 float *folded, *masks, *real4evenl, *real4oddl, *imag4evenl, *imag4oddl, *outx; 
 337               
 338               /* used for setting up plm's */
 339                 double *plm, *saveplm, *latgrid;
 340                 int *indx;
 341               
 342                 double sinBdelta;
 343                 double *plmptr;
 344                 float *maskptr;
 345               
 346                 int nsn, fournsn, snx, maxnsn;
 347                 int lchunksize, lchunkfirst, lchunklast, lchunk, l;
 348                 int lmin, lmax;
 349                 int msize, mx, foldedsize;
 350                 int maprows, nlat, imagesize, latx, poslatx, neglatx, moffset, nlatx;
 351                 int i, m, modd, meven;
 352 tplarson 1.1    int lfirst, llast, ifirst, ilast, lstart, ldone;
 353                 int lfirsteven, llasteven, nevenl, lfirstodd, llastodd, noddl;
 354                 int fromoffset, tooffset, imageoffset;
 355               
 356                 int increment1 = 1; /* for scopy call */
 357                 int increment2 = 2; /* for scopy call */
 358               
 359               /* arguments for sgemm call */
 360                 char transpose[] = "t";
 361                 char normal[] = "n";
 362                 float one = 1.0;
 363                 float zero = 0.0;
 364                 int normflag;
 365                 float cnorm; /* Constant to get proper normalization. */
 366               
 367 tplarson 1.9    double tstart, tepoch, tstep, tround, cadence, nseconds, chunksecs, cadence0;
 368 tplarson 1.1    char *ttotal, *tchunk;
 369                 int nrecs, irec, trecind, bc, iset, ntimechunks;
 370                 int *bad;
 371 tplarson 1.6    int ndt;
 372 tplarson 1.1  
 373               // from jhelio2mlat, i, lmax duplicated.
 374                 double mean, norm=1.0, normx;
 375                 int subtract_mean, normalize, cent_long, zero_miss, lgapod;
 376                 double lgapmin, lgapwidt, lgapmax, lon;
 377               
 378                 int row, col; 
 379                 int lfft, mapped_lmax; 
 380                 int mapcols2;
 381                 int nfft, nmean, nok, nout;
 382               
 383                 float *buf, *bp, *ip, *inp, *op, *outp, *weight, *wp;
 384                 float *wbuf;
 385                 fftwf_plan fftwp;
 386               
 387               // from jv2helio, row, mapped_lmax, maprows, sinBdelta  duplicated
 388                 V2HStatus_t vstat = V2HStatus_Success;
 389                 const char *orientationdef = "SESW    ";
 390                 char *orientation = NULL;
 391                 int paramsign;
 392                 int longitude_shift, velocity_correction, interpolation, apodization;
 393 tplarson 1.1    int mag_correction;
 394                 int mag_offset;
 395                 int sinb_divisions, mapcols, nmax, nmin;
 396                 int carrStretch = 0;
 397                 float diffrotA = 0.0;
 398                 float diffrotB = 0.0;
 399                 float diffrotC = 0.0;
 400                 double tobs, tmearth, tref, trefb0;
 401                 double smajor, sminor, sangle;
 402                 double xscale, yscale, imagescale;
 403                 int xpixels, ypixels, pixels;
 404                 double obs_vr, obs_vw, obs_vn;
 405                 double b0, bmax, bmin;
 406                 double longmax, longmin, longmax_adjusted, longmin_adjusted, longinterval;
 407                 double p0, p, rmax;
 408                 double ierr, perr, psign;
 409                 double x0, y0;
 410                 double obsdist, longshift, obsl0, refl0, mapl0, longrate, rtrue, rsun, S;
 411 tplarson 1.21   double rsunDef, rsunobs;
 412 tplarson 1.1    int obsCR;
 413                 int apel;
 414                 double apinner, apwidth, apx, apy;
 415                 double scale, bias;
 416                 double colsperdeg;
 417               
 418                 double satrot, instrot;
 419                 double dsignout, vsign;
 420                 int distsave;
 421                 double cubsave, tiltasave, tiltbsave, tiltfsave;
 422 tplarson 1.21   LIBPROJECTION_Dist_t distP;
 423 tplarson 1.1  
 424 tplarson 1.2    int errbufstat=setvbuf(stderr, NULL, _IONBF, BUFSIZ);
 425                 int outbufstat=setvbuf(stdout, NULL, _IONBF, BUFSIZ);
 426               
 427 tplarson 1.1    wt0=getwalltime();
 428                 ct0=getcputime(&ut0, &st0);
 429               
 430 tplarson 1.8    inrecquery = (char *)cmdparams_save_str(&cmdparams, "in", &newstat);
 431 tplarson 1.9    outseries = (char *)cmdparams_save_str(&cmdparams, "tsout", &newstat);
 432                 int tsflag = strcmp(kNOTSPECIFIED, outseries);
 433 tplarson 1.8    segnamein = (char *)cmdparams_save_str(&cmdparams, "segin", &newstat);
 434                 segnameout = (char *)cmdparams_save_str(&cmdparams, "segout", &newstat);
 435 tplarson 1.1    int seginflag = strcmp(kNOTSPECIFIED, segnamein);
 436                 int segoutflag = strcmp(kNOTSPECIFIED, segnameout);
 437                 int verbflag = cmdparams_save_int(&cmdparams, "VERB", &newstat);
 438                 int permflag = cmdparams_save_int(&cmdparams, "PERM", &newstat);
 439                 if (permflag)
 440                   lifetime = DRMS_PERMANENT;
 441                 else
 442                   lifetime = DRMS_TRANSIENT;
 443 tplarson 1.8    int forceoutput = cmdparams_save_int(&cmdparams, "FORCEOUTPUT", &newstat);
 444                 char *tag = (char *)cmdparams_save_str(&cmdparams, "TAG", &newstat);
 445 tplarson 1.23   char *version = (char *)cmdparams_save_str(&cmdparams, "VERSION", &newstat);
 446                 int verflag = strcmp(kNOTSPECIFIED, version);
 447 tplarson 1.20   unsigned short calverkey = (unsigned short)cmdparams_save_int(&cmdparams, "CALVERKEY", &newstat);
 448 tplarson 1.1  
 449 tplarson 1.8    char *histlinkname = (char *)cmdparams_save_str(&cmdparams, "histlink", &newstat);
 450                 char *srclinkname = (char *)cmdparams_save_str(&cmdparams, "srclink", &newstat);
 451 tplarson 1.1  
 452 tplarson 1.8    char *v2hout = (char *)cmdparams_save_str(&cmdparams, "v2hout", &newstat);
 453                 char *h2mout = (char *)cmdparams_save_str(&cmdparams, "h2mout", &newstat);
 454 tplarson 1.1    int v2hflag = strcmp(kNOTSPECIFIED, v2hout);
 455                 int h2mflag = strcmp(kNOTSPECIFIED, h2mout);
 456 tplarson 1.14   int histflag = strncasecmp("none", histlinkname, 4);
 457 tplarson 1.1  
 458 tplarson 1.9    if (!v2hflag && !h2mflag && !tsflag)
 459                 {
 460                   fprintf(stderr, "ERROR: no outputs specified.\n");
 461                   return 1; 
 462                 }
 463               
 464 tplarson 1.1    lmin=cmdparams_save_int(&cmdparams, "LMIN", &newstat);
 465                 lmax=cmdparams_save_int(&cmdparams, "LMAX", &newstat);
 466                 lchunksize=cmdparams_save_int(&cmdparams, "LCHUNK", &newstat);
 467                 normflag=cmdparams_save_int(&cmdparams, "NORM", &newstat);
 468               
 469                 tstart=cmdparams_save_time(&cmdparams, "TSTART", &newstat);
 470 tplarson 1.14   sprint_time(tstartstr, tstart, "TAI", 0);
 471 tplarson 1.8    ttotal=(char *)cmdparams_save_str(&cmdparams, "TTOTAL", &newstat);
 472 tplarson 1.23   nseconds=atoinc(ttotal);
 473               
 474               /*
 475                 if (strcmp(kNOTSPECIFIED, ttotal))
 476                 {
 477                   nseconds=atoinc(ttotal);
 478                 }
 479                 else
 480                   nseconds=0.0;
 481               */
 482               /*
 483 arta     1.7    status=drms_names_parseduration(&ttotal, &nseconds, 1);
 484 tplarson 1.16   if (status != DRMS_SUCCESS)
 485 tplarson 1.8    {
 486                   fprintf(stderr, "ERROR: problem parsing TTOTAL, = %s\n", ttotal);
 487                   return 1; 
 488                 }
 489 tplarson 1.23 */
 490 tplarson 1.8    tchunk=(char *)cmdparams_save_str(&cmdparams, "TCHUNK", &newstat);
 491 tplarson 1.1    if (strcmp(kNOTSPECIFIED, tchunk))
 492                 {
 493 tplarson 1.23     chunksecs=atoinc(tchunk);
 494               /*
 495 tplarson 1.8      status=drms_names_parseduration(&tchunk, &chunksecs, 1);
 496 tplarson 1.16     if (status != DRMS_SUCCESS)
 497 tplarson 1.1        newstat = newstat | CPSAVE_UNKNOWN_ERROR;
 498 tplarson 1.23 */
 499 tplarson 1.1    }
 500 tplarson 1.9    else if (!tsflag)
 501                 {
 502                   fprintf(stderr, "ERROR: TCHUNK must be specified if no tsout is given.\n");
 503                   return 1; 
 504                 }
 505 tplarson 1.1    else
 506 tplarson 1.23     chunksecs=0.0;
 507 tplarson 1.1  
 508               
 509                 subtract_mean = cmdparams_save_int(&cmdparams, "SUBMEAN", &newstat);
 510                 normalize = cmdparams_save_int(&cmdparams, "NORMLIZE", &newstat);
 511                 /* CENTLONG=1 centers the longitude Fourier transform on the center
 512                    of the remapped image */
 513                 cent_long = cmdparams_save_int(&cmdparams, "CENTLONG", &newstat);
 514                 /* ZEROMISS=1 sets missing data to 0,
 515                    ZEROMISS=0 fills the output row with missing */
 516                 zero_miss = cmdparams_save_int(&cmdparams, "ZEROMISS", &newstat);
 517                 lgapod = cmdparams_save_int(&cmdparams, "LGAPOD", &newstat);
 518                 lgapmin = cmdparams_save_double(&cmdparams, "LGAPMIN", &newstat);
 519                 lgapwidt = cmdparams_save_double(&cmdparams, "LGAPWIDT", &newstat);
 520                 lgapmax = lgapmin+lgapwidt;
 521               
 522                 int checko = cmdparams_save_int(&cmdparams, "OFLAG", &newstat);
 523 tplarson 1.10   int NaN_beyond_rmax = cmdparams_save_int(&cmdparams, "NAN_BEYOND_RMAX", &newstat);
 524 tplarson 1.1    int maxmissvals = cmdparams_save_int(&cmdparams, "MAXMISSVALS", &newstat);
 525 tplarson 1.10 //  float beyondrmax = cmdparams_save_float(&cmdparams, "BEYONDRMAX", &newstat);
 526 tplarson 1.1  
 527                 carrStretch = cmdparams_save_int(&cmdparams, "CARRSTRETCH", &newstat);
 528                 diffrotA = cmdparams_save_float(&cmdparams, "DIFROT_A", &newstat);
 529                 diffrotB = cmdparams_save_float(&cmdparams, "DIFROT_B", &newstat);
 530                 diffrotC = cmdparams_save_float(&cmdparams, "DIFROT_C", &newstat);
 531               
 532                 longrate = 360.0 / TCARR - 360.0 / DAYSINYEAR; // degrees per day 
 533                 longrate /= SECSINDAY; // degrees per sec 
 534               
 535                 apodization = cmdparams_save_int(&cmdparams, "APODIZE", &newstat);
 536                 apinner = cmdparams_save_double(&cmdparams, "APINNER", &newstat);  
 537                 apwidth = cmdparams_save_double(&cmdparams, "APWIDTH", &newstat);
 538                 apel = cmdparams_save_int(&cmdparams, "APEL", &newstat);
 539                 apx = cmdparams_save_double(&cmdparams, "APX", &newstat);
 540                 apy = cmdparams_save_double(&cmdparams, "APY", &newstat);
 541                 longitude_shift = cmdparams_save_int(&cmdparams, "LGSHIFT", &newstat);
 542                 mag_correction = cmdparams_save_int(&cmdparams, "MCORLEV", &newstat);
 543                 mag_offset = cmdparams_save_int(&cmdparams, "MOFFSETFLAG", &newstat);
 544                 velocity_correction = cmdparams_save_int(&cmdparams, "VCORLEV", &newstat);
 545                 interpolation = cmdparams_save_int(&cmdparams, "INTERPO", &newstat);
 546                 paramsign = cmdparams_save_int(&cmdparams, "DATASIGN", &newstat);
 547 tplarson 1.1    rmax = cmdparams_save_double(&cmdparams, "MAPRMAX", &newstat);
 548                 refl0 = cmdparams_save_double(&cmdparams, "REF_L0", &newstat);
 549               
 550                 distsave = cmdparams_save_int(&cmdparams, "DISTORT", &newstat);
 551                 cubsave = cmdparams_save_double(&cmdparams, "CUBIC", &newstat);
 552                 tiltasave = cmdparams_save_double(&cmdparams, "TILTALPHA", &newstat);
 553                 tiltbsave = cmdparams_save_double(&cmdparams, "TILTBETA", &newstat);
 554                 tiltfsave = cmdparams_save_double(&cmdparams, "TILTFEFF", &newstat);
 555               
 556                 scale = cmdparams_save_double(&cmdparams, "OUTSCALE", &newstat);
 557                 bias = cmdparams_save_double(&cmdparams, "OUTBIAS", &newstat);
 558                 p0 = cmdparams_save_double(&cmdparams, "SOLAR_P", &newstat);
 559                 psign = cmdparams_save_double(&cmdparams, "PSIGN", &newstat);
 560                 perr = cmdparams_save_double(&cmdparams, "PERR", &newstat);
 561                 ierr = cmdparams_save_double(&cmdparams, "IERR", &newstat);
 562                 trefb0 = cmdparams_save_time(&cmdparams, "REF_TB0", &newstat);
 563               
 564                 SetDistort(distsave, cubsave, tiltasave, tiltbsave, tiltfsave, &distP);
 565               
 566                 tref = cmdparams_save_time(&cmdparams, "REF_T0", &newstat);
 567               
 568 tplarson 1.1     // determine mapcols and adjust longmin and longmax */
 569                 mapped_lmax = cmdparams_save_int(&cmdparams, "MAPMMAX", &newstat); 
 570                 longmax = cmdparams_save_double(&cmdparams, "MAPLGMAX", &newstat); /* degrees */
 571                 longmin = cmdparams_save_double(&cmdparams, "MAPLGMIN", &newstat); /* degrees */
 572                 longinterval = (180.0) / mapped_lmax;	                     /* degrees */
 573                
 574                  // This does not always handle the case where 1/longinterval is an integer correctly.
 575               
 576                  // the next two statement do nothing, right? 
 577                  // why do nmin and max keep getting set with different RHSs? 
 578                 nmin = (int)(longmin / longinterval); // round towards 0 
 579                 nmax = (int)(longmax / longinterval); // round towards 0 
 580                 colsperdeg = mapped_lmax / 180.0;
 581                 nmin = (int)(longmin * colsperdeg); // round towards 0 
 582                 nmax = (int)(longmax * colsperdeg); // round towards 0 
 583                 mapcols = nmax - nmin + 1;
 584                 longmin_adjusted = nmin * longinterval;
 585                 longmax_adjusted = nmax * longinterval;
 586               
 587                  // determine maprows, bmax, bmin, and sinBdelta
 588                 sinb_divisions = cmdparams_save_int(&cmdparams, "SINBDIVS", &newstat);
 589 tplarson 1.1    sinBdelta = 1.0/sinb_divisions;
 590                 bmax = cmdparams_save_double(&cmdparams, "MAPBMAX", &newstat);     // degrees
 591                 bmin = -bmax; 
 592                 nmax = (int)(sin(RADSINDEG*bmax)*sinb_divisions); // round towards 0 
 593                 maprows = 2*nmax;
 594               
 595 tplarson 1.8    if (normflag == 0)
 596                   cnorm=1.0;
 597                 else
 598                   cnorm = sqrt(2.)*sinBdelta;
 599               
 600 tplarson 1.1    if (lmax > mapped_lmax || lmin > lmax)
 601                 {
 602                   fprintf(stderr, "ERROR: must have MAPMMAX >= LMAX >= LMIN, MAPMMAX = %d, LMAX= %d, LMIN = %d\n", mapped_lmax, lmax, lmin);
 603                   return 1;
 604                 }
 605               
 606 tplarson 1.8    if (newstat) 
 607                 {
 608                   fprintf(stderr, "ERROR: problem with input arguments, status = %d, diagnosis follows\n", newstat);
 609                   cpsave_decode_error(newstat);
 610                   return 1;
 611                 }  
 612                 else if (savestrlen != strlen(savestr)) 
 613                 {
 614                   fprintf(stderr, "ERROR: problem with savestr, savestrlen = %d, strlen(savestr) = %d\n", savestrlen, (int)strlen(savestr));
 615                   return 1;
 616                 }
 617               
 618 tplarson 1.9    DRMS_Record_t *tempoutrec;
 619                 DRMS_Link_t *histlink;
 620                 int itest;
 621 tplarson 1.21 /*
 622               // 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.
 623 tplarson 1.17   char *cvsinfo;
 624                 cvsinfo = (char *)malloc(1024);
 625 tplarson 1.24   strcpy(cvsinfo,"$Header: /home/cvsuser/cvsroot/JSOC/proj/globalhs/apps/jv2ts.c,v 1.23 2013/07/02 20:32:03 tplarson Exp $");
 626 tplarson 1.17   strcat(cvsinfo,"\n");
 627                 strcat(cvsinfo,getshtversion());
 628 tplarson 1.21 */
 629 tplarson 1.9  // assume all output dataseries link to the same dataseries for HISTORY
 630                 if (tsflag)
 631                 {
 632                   tempoutrec = drms_create_record(drms_env, outseries, DRMS_TRANSIENT, &status);
 633                   if (status != DRMS_SUCCESS) 
 634                   {
 635                    fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", outseries, status);
 636                    return 1;
 637                   }
 638 tplarson 1.1  
 639 tplarson 1.14     DRMS_Keyword_t *outkeytest = hcon_lookup_lower(&tempoutrec->keywords, "MAPMMAX");
 640                   if (outkeytest != NULL && outkeytest->info->recscope == 1)
 641                   {
 642                     int mapmmaxout=drms_getkey_int(tempoutrec, "MAPMMAX", &status);
 643                     if (mapmmaxout != mapped_lmax)
 644                     {
 645                      fprintf(stderr,"ERROR: output MAPMMAX=%d does not match input parameter MAPMMAX=%d, status = %d\n", mapmmaxout, mapped_lmax, status);
 646                      return 1;
 647                     }
 648                   }
 649               
 650                   outkeytest = hcon_lookup_lower(&tempoutrec->keywords, "SINBDIVS");
 651                   if (outkeytest != NULL && outkeytest->info->recscope == 1)
 652 tplarson 1.9      {
 653 tplarson 1.14       int sinbdivsout=drms_getkey_int(tempoutrec, "SINBDIVS", &status);
 654                     if (sinbdivsout != sinb_divisions)
 655 tplarson 1.9        {
 656 tplarson 1.14        fprintf(stderr,"ERROR: output SINBDIVS=%d does not match input parameter SINBDIVS=%d, status = %d\n", sinbdivsout, sinb_divisions, status);
 657                      return 1;
 658 tplarson 1.9        }
 659                   }
 660 tplarson 1.14 
 661               // set up ancillary dataseries for processing metadata
 662                   if (histflag)
 663 tplarson 1.9      {
 664 tplarson 1.14       histlink = hcon_lookup_lower(&tempoutrec->links, histlinkname);
 665                     if (histlink != NULL) 
 666                     {
 667 tplarson 1.21         histrecnum=set_history(histlink);
 668 tplarson 1.14         if (histrecnum < 0)
 669                       {
 670                         drms_close_record(tempoutrec, DRMS_FREE_RECORD);
 671                         return 1;
 672                       }
 673                     }
 674                     else
 675                     {
 676                       fprintf(stderr,"WARNING: could not find history link in output dataseries\n");
 677                     }
 678 tplarson 1.9      }
 679 tplarson 1.1  
 680 tplarson 1.9  // these must be present in the output dataseries and variable, not links or constants   
 681 tplarson 1.14     char *outchecklist[] = {"T_START", "QUALITY", "LMIN", "LMAX", "NDT"};
 682 tplarson 1.9      for (itest=0; itest < ARRLENGTH(outchecklist); itest++)
 683                   {
 684                     DRMS_Keyword_t *outkeytest = hcon_lookup_lower(&tempoutrec->keywords, outchecklist[itest]);
 685                     if (outkeytest == NULL || outkeytest->info->islink || outkeytest->info->recscope == 1)
 686                     {
 687                       fprintf(stderr, "ERROR: output keyword %s is either missing, constant, or a link\n", outchecklist[itest]);
 688                       drms_close_record(tempoutrec, DRMS_FREE_RECORD);
 689                       return 1;
 690                     }
 691                   }
 692 tplarson 1.1  
 693 tplarson 1.9      cadence0=drms_getkey_float(tempoutrec, "T_STEP", &status);
 694                   tepoch=drms_getkey_time(tempoutrec, "T_START_epoch", &status);
 695                   tstep=drms_getkey_float(tempoutrec, "T_START_step", &status);
 696                   tround=drms_getkey_float(tempoutrec, "T_START_round", &status);
 697                   if (fmod(tstart-tepoch,tstep) > tround/2)
 698                   {
 699 tplarson 1.14       sprint_time(trecstr, tepoch, "TAI", 0);
 700                     fprintf(stderr, "ERROR: output dataseries seems incompatible with input parameters (tstep must divide tstart-tepoch): TSTART = %s, T_START_epoch = %s, tstep = %f\n", 
 701                                                                                                                                           tstartstr, trecstr, tstep);
 702 tplarson 1.9        drms_close_record(tempoutrec, DRMS_FREE_RECORD);
 703                     return 1;
 704                   }
 705                   if (chunksecs == 0.0)
 706                     chunksecs = tstep;
 707                   else if (fmod(chunksecs,tstep))
 708 tplarson 1.1      {
 709 tplarson 1.9        fprintf(stderr, "ERROR: output dataseries seems incompatible with input parameters (tstep must divide chunksecs): chunksecs = %f, tstep = %f\n", chunksecs, tstep);
 710 tplarson 1.4        drms_close_record(tempoutrec, DRMS_FREE_RECORD);
 711 tplarson 1.1        return 1;
 712                   }
 713 tplarson 1.9  
 714 tplarson 1.14     drms_close_record(tempoutrec, DRMS_FREE_RECORD);
 715 tplarson 1.1    }
 716 tplarson 1.14 
 717                 if (v2hflag)
 718 tplarson 1.1    {
 719 tplarson 1.9      tempoutrec = drms_create_record(drms_env, v2hout, DRMS_TRANSIENT, &status);
 720                   if (status != DRMS_SUCCESS) 
 721                   {
 722                    fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", v2hout, status);
 723                    return 1;
 724                   }
 725               
 726               // set up ancillary dataseries for processing metadata
 727 tplarson 1.14     if (histflag && histrecnum < 0)
 728 tplarson 1.9      {
 729 tplarson 1.14       histlink = hcon_lookup_lower(&tempoutrec->links, histlinkname);
 730                     if (histlink != NULL) 
 731 tplarson 1.9        {
 732 tplarson 1.21         histrecnum=set_history(histlink);
 733 tplarson 1.14         if (histrecnum < 0)
 734                       {
 735                         drms_close_record(tempoutrec, DRMS_FREE_RECORD);
 736                         return 1;
 737                       }
 738                     }
 739                     else
 740                     {
 741                       fprintf(stderr,"WARNING: could not find history link in output dataseries\n");
 742 tplarson 1.9        }
 743                   }
 744 tplarson 1.1  
 745               // these must be present in the output dataseries and variable, not links or constants   
 746 tplarson 1.9      char *outchecklist[] = {"T_REC", "QUALITY", "CRPIX1", "CRVAL1", "CDELT1", "CRPIX2", "CROTA2", "CDELT2" };
 747                   for (itest=0; itest < ARRLENGTH(outchecklist); itest++)
 748 tplarson 1.1      {
 749 tplarson 1.9        DRMS_Keyword_t *outkeytest = hcon_lookup_lower(&tempoutrec->keywords, outchecklist[itest]);
 750                     if (outkeytest == NULL || outkeytest->info->islink || outkeytest->info->recscope == 1)
 751                     {
 752                       fprintf(stderr, "ERROR: output keyword %s is either missing, constant, or a link\n", outchecklist[itest]);
 753                       drms_close_record(tempoutrec, DRMS_FREE_RECORD);
 754                       return 1;
 755                     }
 756 tplarson 1.1      }
 757               
 758 tplarson 1.14     drms_close_record(tempoutrec, DRMS_FREE_RECORD);
 759 tplarson 1.4    }
 760 tplarson 1.14 
 761                 if (h2mflag)
 762 tplarson 1.4    {
 763 tplarson 1.9      tempoutrec = drms_create_record(drms_env, h2mout, DRMS_TRANSIENT, &status);
 764                   if (status != DRMS_SUCCESS) 
 765                   {
 766                    fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", h2mout, status);
 767                    return 1;
 768                   }
 769               
 770               // set up ancillary dataseries for processing metadata
 771 tplarson 1.14     if (histflag && histrecnum < 0)
 772 tplarson 1.9      {
 773 tplarson 1.14       histlink = hcon_lookup_lower(&tempoutrec->links, histlinkname);
 774                     if (histlink != NULL) 
 775 tplarson 1.9        {
 776 tplarson 1.21         histrecnum=set_history(histlink);
 777 tplarson 1.14         if (histrecnum < 0)
 778                       {
 779                         drms_close_record(tempoutrec, DRMS_FREE_RECORD);
 780                         return 1;
 781                       }
 782                     }
 783                     else
 784                     {
 785                       fprintf(stderr,"WARNING: could not find history link in output dataseries\n");
 786 tplarson 1.9        }
 787                   }
 788               
 789               // these must be present in the output dataseries and variable, not links or constants   
 790                   char *outchecklist[] = {"T_REC", "QUALITY", "CRPIX1", "CDELT1", "CRPIX2", "CDELT2" };
 791                   for (itest=0; itest < ARRLENGTH(outchecklist); itest++)
 792                   {
 793                     DRMS_Keyword_t *outkeytest = hcon_lookup_lower(&tempoutrec->keywords, outchecklist[itest]);
 794                     if (outkeytest == NULL || outkeytest->info->islink || outkeytest->info->recscope == 1)
 795                     {
 796                       fprintf(stderr, "ERROR: output keyword %s is either missing, constant, or a link\n", outchecklist[itest]);
 797                       drms_close_record(tempoutrec, DRMS_FREE_RECORD);
 798                       return 1;
 799                     }
 800                   }
 801               
 802 tplarson 1.14     drms_close_record(tempoutrec, DRMS_FREE_RECORD);
 803 tplarson 1.4    }
 804 tplarson 1.14 
 805 tplarson 1.9  
 806 tplarson 1.4    if (fmod(nseconds,chunksecs) != 0.0)
 807                 {
 808 tplarson 1.14     fprintf(stderr, "ERROR: input parameters seem incompatible (chunksecs must divide totalsecs): totalsecs = %f, chunksecs = %f\n", nseconds, chunksecs);
 809 tplarson 1.8      return 1;
 810 tplarson 1.4    }
 811                 ntimechunks=nseconds/chunksecs;
 812               
 813 tplarson 1.8    inrecset = drms_open_recordset(drms_env, inrecquery, &status);
 814                 if (status != DRMS_SUCCESS || inrecset == NULL)
 815                 {
 816                   fprintf(stderr, "ERROR: problem opening input recordset: status = %d\n", status);
 817                   return 1;
 818                 }
 819 tplarson 1.1  
 820 tplarson 1.20   int nrecsin = drms_count_records(drms_env, inrecquery, &status);
 821                 if (status != DRMS_SUCCESS)
 822                 {
 823                   fprintf(stderr, "ERROR: problem counting input records: status = %d, nrecs = %d\n", status, nrecsin);
 824                   drms_close_records(inrecset, DRMS_FREE_RECORD);
 825                   return 1;
 826                 }
 827                 if (nrecsin == 0)
 828                 {
 829                   fprintf(stderr, "ERROR: input recordset contains no records. if such was intended use jretile instead.\n");
 830                   drms_close_records(inrecset, DRMS_FREE_RECORD);
 831                   return 1;
 832                 }
 833               
 834               //the above replaces the following.  drms_open_recordset() no longer fills in the number of records.
 835               /*
 836 tplarson 1.8    if (inrecset->n == 0)
 837 tplarson 1.1    {
 838 tplarson 1.8      fprintf(stderr, "ERROR: input recordset contains no records. if such was intended use jretile instead.\n");
 839                   drms_close_records(inrecset, DRMS_FREE_RECORD);
 840                   return 1;
 841 tplarson 1.1    }
 842 tplarson 1.20 */
 843 tplarson 1.1  
 844                 if (verbflag) 
 845 tplarson 1.20     printf("input recordset opened, nrecs = %d\n", nrecsin);
 846 tplarson 1.1  
 847 tplarson 1.8    inrec = drms_recordset_fetchnext(drms_env, inrecset, &fetchstat, &chunkstat, NULL);
 848 tplarson 1.1  
 849 tplarson 1.8  // these must be present in the input dataseries
 850 tplarson 1.12   char *inchecklist[] = {"T_REC", "QUALITY", "T_OBS", "CRLT_OBS", "CRLN_OBS", "CADENCE",
 851 tplarson 1.14                      //     "SAT_ROT", "INST_ROT", "IM_SCALE",
 852 tplarson 1.6                            "CDELT1", "CDELT2"};
 853 tplarson 1.1  
 854 tplarson 1.21   DRMS_Keyword_t *inkeytest;
 855 tplarson 1.1    for (itest=0; itest < ARRLENGTH(inchecklist); itest++)
 856                 {
 857 tplarson 1.21     inkeytest = hcon_lookup_lower(&inrec->keywords, inchecklist[itest]);
 858 tplarson 1.8      if (inkeytest == NULL)
 859 tplarson 1.1      {
 860                     fprintf(stderr, "ERROR: required input keyword %s is missing\n", inchecklist[itest]);
 861 tplarson 1.8        drms_close_records(inrecset, DRMS_FREE_RECORD);
 862                     return 1;
 863 tplarson 1.1      }
 864                 }
 865               
 866 tplarson 1.21   int readrsunref=0;
 867                 double rsunref;
 868                 inkeytest = hcon_lookup_lower(&inrec->keywords, "RSUN_REF");
 869                 if (inkeytest == NULL)
 870                   rtrue = RTRUE/AU;
 871                 else if (inkeytest->info->recscope == 1)
 872                 {
 873                   rsunref = drms_getkey_double(inrec, "RSUN_REF", &status);
 874                   ParameterDef(status, "RSUN_REF", RTRUE, &rsunref, inrec->recnum, 1);
 875                   rtrue=rsunref/AU;
 876                 }
 877                 else
 878                   readrsunref=1;
 879 tplarson 1.1  
 880                 trec = drms_getkey_time(inrec, "T_REC", &status);
 881 tplarson 1.8    if (status != DRMS_SUCCESS)
 882 tplarson 1.1    {
 883                   fprintf(stderr, "ERROR: problem with required parameter T_REC: status = %d, recnum = %lld\n", status, inrec->recnum);
 884 tplarson 1.8      drms_close_records(inrecset, DRMS_FREE_RECORD);
 885                   return 1;
 886 tplarson 1.1    }
 887                 sprint_time(trecstr, trec, "TAI", 0);
 888               
 889                 cadence=drms_getkey_float(inrec, "CADENCE", &status);
 890 tplarson 1.8    if (status != DRMS_SUCCESS)
 891 tplarson 1.1    {
 892 tplarson 1.14     fprintf(stderr, "ERROR: problem with required parameter CADENCE: status = %d, T_REC = %s, recnum = %lld\n", status, trecstr, inrec->recnum);
 893 tplarson 1.8      drms_close_records(inrecset, DRMS_FREE_RECORD);
 894                   return 1;
 895 tplarson 1.1    }
 896 tplarson 1.11 
 897 tplarson 1.9    if (!forceoutput)
 898                 {
 899 tplarson 1.20     if (nrecsin != nseconds/cadence)
 900 tplarson 1.9      {
 901                     fprintf(stderr, "ERROR: input recordset does not contain a record for every slot.\n");
 902                     drms_close_records(inrecset, DRMS_FREE_RECORD);
 903                     return 1;
 904                   }
 905                 }
 906 tplarson 1.6  
 907 tplarson 1.9    if (tsflag && cadence != cadence0)
 908 tplarson 1.8    {
 909 tplarson 1.14     fprintf(stderr, "ERROR: input CADENCE does not match output T_STEP: status = %d, T_REC = %s, recnum = %lld\n", status, trecstr, inrec->recnum);
 910 tplarson 1.8      drms_close_records(inrecset, DRMS_FREE_RECORD);
 911                   return 1;
 912                 }
 913 tplarson 1.1  
 914                 nrecs=chunksecs/cadence;
 915                 maxnsn=nsn=nrecs;
 916                 fournsn=4*nsn;
 917               
 918                 if (verbflag) 
 919                   printf("ntimechunks = %d, recs per timechunk = %d\n", ntimechunks, nrecs);
 920               
 921               
 922                 if (trec >= tstart + nseconds)
 923                 {
 924 tplarson 1.4      fprintf(stderr, "ERROR: no records processed: first input record is after last output record: T_REC = %s\n", trecstr);
 925 tplarson 1.8      drms_close_records(inrecset, DRMS_FREE_RECORD);
 926                   return 1;
 927 tplarson 1.1    }
 928               
 929                 while (trec < tstart && chunkstat != kRecChunking_NoMoreRecs)
 930                 {
 931 tplarson 1.14     fprintf(stderr, "WARNING: input record will not be included in output: T_REC = %s, TSTART = %s \n", trecstr, tstartstr);
 932 tplarson 1.8      inrec = drms_recordset_fetchnext(drms_env, inrecset, &fetchstat, &chunkstat, NULL);
 933                   if (inrec != NULL)
 934 tplarson 1.1      {
 935                     trec = drms_getkey_time(inrec, "T_REC", &status);
 936                     sprint_time(trecstr, trec, "TAI", 0);
 937                   }
 938                 }
 939                 if (chunkstat == kRecChunking_NoMoreRecs)
 940                 {
 941 tplarson 1.4      fprintf(stderr,"ERROR: no records processed: last input record is before first output record: T_REC = %s\n", trecstr);
 942 tplarson 1.8      drms_close_records(inrecset, DRMS_FREE_RECORD);
 943                   return 1;
 944 tplarson 1.1    }
 945               
 946                 msize = lmax+1;
 947                 if (lchunksize == 0) lchunksize = msize;
 948               
 949                 nlat = maprows/2;
 950                 imagesize = maprows*2*msize; /* out image could be smaller than in */
 951               
 952                 nout = 2 * (lmax + 1);
 953               
 954                 lfft = 2 * mapped_lmax;
 955                 nfft = lfft + 2;
 956                 mapcols2 = mapcols/2;
 957               
 958               /* Let's try this since SGI's like odd leading dimensions of the first
 959                  array in sgemm */
 960 tplarson 1.14 //  nlatx=2*(nlat/2)+1;
 961 tplarson 1.1  
 962               /* make nlatx divisible by 4 on linux systems */
 963 tplarson 1.14 //#ifdef __linux__
 964 tplarson 1.1    if (nlat % 4)
 965                   nlatx=4*(nlat/4+1);
 966                 else
 967                   nlatx=nlat;
 968 tplarson 1.14 //#endif
 969 tplarson 1.1  
 970 tplarson 1.14   DRMS_RecordSet_t *outrecset, *v2hrecset, *h2mrecset;
 971 tplarson 1.9    if (tsflag)
 972                 {
 973                   real4evenl = (float *)(malloc (nlatx*maxnsn*sizeof(float)));
 974                   real4oddl = (float *)(malloc (nlatx*maxnsn*sizeof(float)));
 975                   imag4evenl = (float *)(malloc (nlatx*maxnsn*sizeof(float)));
 976                   imag4oddl = (float *)(malloc (nlatx*maxnsn*sizeof(float)));
 977                   outx = (float *)(malloc (maxnsn*2*lchunksize*sizeof(float)));
 978               
 979                   plm = (double *)(malloc ((lmax+1)*nlat*sizeof(double)));  
 980                   saveplm = (double *)(malloc ((lmax+1)*nlat*2*sizeof(double)));
 981                   latgrid = (double *)(malloc (nlat*sizeof(double)));
 982                   for (i=0; i<nlat; i++) latgrid[i] = (i+0.5)*sinBdelta;
 983               
 984                   indx = (int *)(malloc ((lmax+1)*sizeof(int)));
 985                   for (l=0; l<=lmax; l++) indx[l]=l;
 986               
 987                   masks = (float *)(malloc (nlat*lchunksize*sizeof(float)));
 988                   foldedsize = 4*nlat*(lmax+1)*maxnsn;
 989                   folded = (float *)(malloc (foldedsize*sizeof(float)));
 990                   oddpart = (float *)(malloc (nlat*sizeof(float)));
 991                   evenpart = (float *)(malloc (nlat*sizeof(float)));
 992 tplarson 1.14 
 993                   lchunkfirst = lmin/lchunksize;
 994                   lchunklast = lmax/lchunksize;
 995                   int nlchunks = (lchunklast - lchunkfirst) + 1;
 996                   int nrecsout = nlchunks*ntimechunks;
 997                   outrecset = drms_create_records(drms_env, nrecsout, outseries, lifetime, &status);
 998                   if (status != DRMS_SUCCESS || outrecset == NULL)
 999                   {
1000                     fprintf(stderr,"ERROR: unable to create records in output dataseries %s, status = %d\n", outseries, status);
1001                     drms_close_records(inrecset, DRMS_FREE_RECORD);
1002                     return 1;
1003                   }
1004               
1005                 }
1006               
1007                 if (v2hflag)
1008                 {
1009 tplarson 1.20     v2hrecset = drms_create_records(drms_env, nrecsin, v2hout, lifetime, &status);
1010 tplarson 1.14     if (status != DRMS_SUCCESS || v2hrecset == NULL)
1011                   {
1012                     fprintf(stderr,"ERROR: unable to create records in output dataseries %s, status = %d\n", v2hout, status);
1013                     drms_close_records(inrecset, DRMS_FREE_RECORD);
1014                     return 1;
1015                   }
1016                 }
1017               
1018                 if (h2mflag)
1019                 {
1020 tplarson 1.20     h2mrecset = drms_create_records(drms_env, nrecsin, h2mout, lifetime, &status);
1021 tplarson 1.14     if (status != DRMS_SUCCESS || h2mrecset == NULL)
1022                   {
1023                     fprintf(stderr,"ERROR: unable to create records in output dataseries %s, status = %d\n", h2mout, status);
1024                     drms_close_records(inrecset, DRMS_FREE_RECORD);
1025                     return 1;
1026                   }
1027 tplarson 1.9    }
1028 tplarson 1.1  
1029 tplarson 1.14 
1030 tplarson 1.1    bad = (int *)(malloc (nrecs*sizeof(int)));
1031                 v2hptr = (float *)(malloc(maprows*mapcols*sizeof(float)));
1032                 h2mptr = (float *)(malloc(maprows*nout*sizeof(float)));
1033               
1034                   /* get working buffer */
1035                 buf = (float *)malloc(nfft * sizeof(float));
1036               
1037                 wbuf = (float *)malloc(nfft * sizeof(float));
1038                 fftwp = fftwf_plan_r2r_1d(lfft, buf, wbuf, FFTW_R2HC, FFTW_ESTIMATE);
1039               
1040                   /* get weight array for apodizing */
1041                 weight = (float *)malloc(nfft * sizeof(float));
1042               
1043                 wp = weight;
1044                 for (col=0; col<mapcols; col++) 
1045                 {
1046                   if (lgapod) 
1047                   {
1048                     lon=abs(col-mapcols2)*360.0/(2*mapped_lmax);
1049                     if (lon < lgapmin)
1050                       *wp++=1.0;
1051 tplarson 1.1        else if (lon < lgapmax)
1052                       *wp++=0.5+0.5*cos(PI*(lon-lgapmin)/lgapwidt);
1053                     else
1054                       *wp++=0.0;
1055                   }
1056                   else 
1057                     *wp++ = 1.0;
1058                 }
1059               
1060 tplarson 1.8    status=drms_stage_records(inrecset, 1, 0);
1061                 if (status != DRMS_SUCCESS)
1062                 {
1063                   fprintf(stderr, "ERROR: drms_stage_records returned status = %d\n", status);
1064                   return 1;
1065                 }
1066 tplarson 1.1  
1067 tplarson 1.20   unsigned long long calversout, calvers;
1068 tplarson 1.15   int calversunset=1;
1069 tplarson 1.20   unsigned int nybblearrout[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
1070                 int fixflagarr[16]            = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
1071                 for (i=0;i<16;i++)
1072                 {
1073                   if (getbits(calverkey,i,1))
1074                     fixflagarr[i]=1;
1075                 }
1076               
1077                 int mixflag=0;
1078 tplarson 1.15 
1079 tplarson 1.4    int nrecords=0;
1080                 int nsegments=0;
1081                 int error=0;
1082                 int nodata=0;
1083 tplarson 1.14   int irecout=0;
1084                 int iv2hrec=0;
1085                 int ih2mrec=0;
1086 tplarson 1.1    for (iset=0; iset < ntimechunks && chunkstat != kRecChunking_NoMoreRecs; iset++)
1087                 {
1088                   sprint_time(tstartstr, tstart, "TAI", 0);
1089                   if (verbflag)
1090                   {
1091                     wt1=getwalltime();
1092                     ct1=getcputime(&ut1, &st1);
1093                     printf("processing timechunk %d, tstart = %s\n", iset, tstartstr);
1094                   }
1095               
1096                   if (trec >= tstart+chunksecs)
1097                   {
1098 tplarson 1.8        if (forceoutput)
1099                     {
1100                       nodata=1;
1101                       goto skip_norecs;
1102                     }
1103                     else
1104                     {
1105                       fprintf(stderr, "ERROR: no data for timechunk beginning at %s\n", tstartstr);
1106                       error++;
1107                       tstart+=chunksecs;
1108                       continue;
1109                     }
1110 tplarson 1.1      }
1111               
1112 tplarson 1.4      while (trec < tstart && chunkstat != kRecChunking_NoMoreRecs)
1113                   {
1114 tplarson 1.8        inrec = drms_recordset_fetchnext(drms_env, inrecset, &fetchstat, &chunkstat, NULL);
1115 tplarson 1.6        if (inrec != NULL)
1116 tplarson 1.4        {
1117                       trec = drms_getkey_time(inrec, "T_REC", &status);
1118                       sprint_time(trecstr, trec, "TAI", 0);
1119                     }
1120                   }
1121               
1122 tplarson 1.1      bc=0;
1123 tplarson 1.4      nodata=0;
1124 tplarson 1.20     mixflag=0;
1125                   calversunset=1;
1126 tplarson 1.8      trecind=(trec-tstart+cadence/2)/cadence;
1127 tplarson 1.1  
1128 tplarson 1.8      for (irec=0; irec < nrecs && chunkstat != kRecChunking_NoMoreRecs; irec++)
1129 tplarson 1.1      {
1130 tplarson 1.8  
1131                     if (trecind > irec)
1132               //some inputs were missing
1133 tplarson 1.1        {
1134 tplarson 1.8          if (forceoutput)
1135                       {
1136                         bad[bc++]=irec;
1137                         continue;
1138                       }
1139                       else
1140                       {
1141                         fprintf(stderr, "ERROR: some input records missing, T_START = %s, T_REC = %s, irec = %d\n", tstartstr, trecstr, irec);
1142                         error++;
1143                         goto continue_outer_loop;
1144                       }
1145                     }
1146               
1147                     while (trecind < irec)
1148               //T_REC is duplicated in input
1149                     {
1150                       if (forceoutput)
1151                       {
1152                         inrec = drms_recordset_fetchnext(drms_env, inrecset, &fetchstat, &chunkstat, NULL);
1153                         if (inrec != NULL)
1154                         {
1155 tplarson 1.8              trec = drms_getkey_time(inrec, "T_REC", &status);
1156                           sprint_time(trecstr, trec, "TAI", 0);
1157                           trecind=(trec-tstart+cadence/2)/cadence;
1158                         }
1159                       }
1160                       else
1161                       {
1162                         fprintf(stderr, "ERROR: some input records have duplicate T_REC, T_START = %s, T_REC = %s, irec = %d\n", tstartstr, trecstr, irec);
1163                         error++;
1164                         goto continue_outer_loop;
1165                       }
1166 tplarson 1.1        }
1167               
1168                     if (verbflag > 1) 
1169                     {
1170                       wt2=getwalltime();
1171                       ct2=getcputime(&ut2, &st2);
1172                       printf("  processing record %d\n", irec);
1173                     }
1174               
1175                     quality=drms_getkey_int(inrec, "QUALITY", &status);
1176                     if (status != DRMS_SUCCESS || (quality & QUAL_NODATA)) //may want stricter test on quality here
1177                     {
1178                       bad[bc++]=irec;
1179 tplarson 1.18         if (verbflag > 2)
1180 tplarson 1.8            fprintf(stderr, "SKIP: image rejected based on quality: T_REC = %s, quality = %08x\n", trecstr, quality);
1181 tplarson 1.1          goto skip;
1182                     }
1183               
1184 tplarson 1.20       if (tsflag)
1185 tplarson 1.15       {
1186 tplarson 1.20         if (calversunset)
1187                       {
1188                         calversout=drms_getkey_longlong(inrec, "CALVER64", &status);
1189                         if (status != DRMS_SUCCESS)
1190                           calversout = 0;
1191                         else
1192                           calversout = fixcalver64(calversout);
1193                         calversunset=0;
1194               
1195                         for (i=0;i<16;i++)
1196                           nybblearrout[i]=getbits(calversout,4*i+3,4);
1197               
1198                       }
1199               
1200                       calvers=drms_getkey_longlong(inrec, "CALVER64", &status);
1201 tplarson 1.15         if (status != DRMS_SUCCESS)
1202 tplarson 1.20           calvers = 0;
1203 tplarson 1.18         else
1204 tplarson 1.20           calvers = fixcalver64(calvers);
1205 tplarson 1.15 
1206 tplarson 1.20         for (i=0;i<16;i++)
1207                       {
1208                         int nybble=getbits(calvers,4*i+3,4);
1209                         if (fixflagarr[i])
1210                         {
1211                           if (nybble != nybblearrout[i])
1212                           {
1213                             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);
1214                             error++;
1215                             goto continue_outer_loop;
1216                           }
1217                         }
1218                         else
1219                         {
1220                           if (nybble < nybblearrout[i])
1221                             nybblearrout[i]=nybble;
1222                         }
1223                       }
1224 tplarson 1.15 
1225 tplarson 1.20         if (!mixflag && calvers != calversout)
1226                         mixflag=1;
1227 tplarson 1.15       }
1228               
1229 tplarson 1.20 
1230 tplarson 1.1        if (seginflag)
1231                       segin = drms_segment_lookup(inrec, segnamein);
1232                     else
1233                       segin = drms_segment_lookupnum(inrec, 0);
1234 tplarson 1.16       if (segin != NULL)
1235 tplarson 1.1          inarr = drms_segment_read(segin, usetype, &status);
1236               
1237 tplarson 1.8        if (segin == NULL || inarr == NULL || status != DRMS_SUCCESS)
1238 tplarson 1.1        {
1239 tplarson 1.8          fprintf(stderr, "ERROR: problem with input segment or array: status = %d, T_REC = %s, recnum = %lld, histrecnum = %lld\n", status, trecstr, inrec->recnum, histrecnum);
1240                       return 0;
1241 tplarson 1.1        }
1242               
1243                     if (maxmissvals > 0) 
1244                     {
1245                       int missvals = drms_getkey_int(inrec, "MISSVALS", &status);
1246                       PARAMETER_ERROR("MISSVALS")
1247                       if (missvals > maxmissvals) 
1248                       {
1249                         bad[bc++]=irec;
1250 tplarson 1.8            if (verbflag > 1)
1251                           fprintf(stderr, "SKIP: %d pixels MISSING, max allowed is %d: T_REC = %s, recnum = %lld\n", missvals, maxmissvals, trecstr, inrec->recnum);
1252 tplarson 1.1            drms_free_array(inarr);
1253                         goto skip;
1254                       }
1255                     }
1256               
1257                     tobs = drms_getkey_time(inrec, "T_OBS", &status);
1258                     PARAMETER_ERROR("T_OBS")
1259               
1260                     // MDI keyword was OBS_B0
1261                     b0 = drms_getkey_double(inrec, "CRLT_OBS", &status);
1262                     PARAMETER_ERROR("CRLT_OBS")
1263               
1264                     // MDI keyword was OBS_L0
1265                     obsl0 = drms_getkey_double(inrec, "CRLN_OBS", &status);
1266                     PARAMETER_ERROR("CRLN_OBS")
1267               
1268                     if (p0 == 999.0) 
1269                     {
1270                        // MDI keyword was SOLAR_P = -(SAT_ROT + INST_ROT)
1271 tplarson 1.6  /*
1272 tplarson 1.1           satrot = drms_getkey_double(inrec, "SAT_ROT", &status);
1273                        PARAMETER_ERROR("SAT_ROT")
1274                        instrot = drms_getkey_double(inrec, "INST_ROT", &status);
1275                        PARAMETER_ERROR("INST_ROT")
1276                        p=-(satrot+instrot);
1277 tplarson 1.6  */
1278                        double crota = drms_getkey_double(inrec, "CROTA2", &status);
1279                        PARAMETER_ERROR("CROTA2")
1280                        p=-crota;
1281 tplarson 1.1        } 
1282                     else 
1283                     {
1284                        p = p0;
1285                     }
1286               
1287                     p = psign * p ;
1288                     b0 = b0 + ierr * sin((tobs - trefb0) / 31557600. * 2 * PI);
1289                     p = p + perr - ierr * cos((tobs - trefb0) / 31557600. * 2 * PI);
1290               
1291                     // S_MAJOR, S_MINOR, S_ANGLE, X_SCALE, Y_SCALE were MDI keywords, not used for HMI, but still necessary for GONG data
1292                     smajor = drms_getkey_double(inrec, "S_MAJOR", &status);
1293 tplarson 1.8        ParameterDef(status, "S_MAJOR", 1.0, &smajor, inrec->recnum, 0);
1294 tplarson 1.1  
1295                     sminor = drms_getkey_double(inrec, "S_MINOR", &status);
1296 tplarson 1.8        ParameterDef(status, "S_MINOR", 1.0, &sminor, inrec->recnum, 0);
1297 tplarson 1.1  
1298                     sangle = drms_getkey_double(inrec, "S_ANGLE", &status);
1299 tplarson 1.8        ParameterDef(status, "S_ANGLE", 0.0, &sangle, inrec->recnum, 0);
1300 tplarson 1.1  
1301 tplarson 1.21       /*
1302                     our calculation of CDELTi does not follow WCS conventions.  it should be the plate scale
1303                     at the reference pixel (disk center), but instead we use the average between center and limb.
1304                     this is taken into account in the calculation of rsun below.
1305                     */
1306 tplarson 1.1        xscale = drms_getkey_double(inrec, "CDELT1", &status);
1307                     PARAMETER_ERROR("CDELT1")
1308                     yscale = drms_getkey_double(inrec, "CDELT2", &status);
1309                     PARAMETER_ERROR("CDELT2")
1310               
1311                     // use xscale and yscale for the following check, then set to 1.0 for the call to obs2helio
1312                     if (xscale != yscale)
1313                     {
1314 tplarson 1.8          fprintf(stderr, "ERROR: CDELT1 != CDELT2 not supported, CDELT1 = %f, CDELT2 = %f: T_REC = %s, recnum = %lld \n", xscale, yscale, trecstr, inrec->recnum);
1315 tplarson 1.1          drms_free_array(inarr);
1316 tplarson 1.4          error++;
1317 tplarson 1.8          goto continue_outer_loop;
1318 tplarson 1.1        }
1319 tplarson 1.13       imagescale=xscale;
1320 tplarson 1.1        xscale=1.0;
1321                     yscale=1.0;
1322               
1323 tplarson 1.6  /*
1324 tplarson 1.1        imagescale = drms_getkey_double(inrec, "IM_SCALE", &status);
1325                     PARAMETER_ERROR("IM_SCALE")
1326 tplarson 1.6  */
1327 tplarson 1.13 
1328 tplarson 1.1        if (paramsign != 0)
1329                     {
1330                        vsign = paramsign;
1331                     }
1332                     else
1333                     {
1334                        vsign = drms_getkey_double(inrec, "DATASIGN", &status);
1335 tplarson 1.8           ParameterDef(status, "DATASIGN", 1.0, &vsign, inrec->recnum, 1);
1336 tplarson 1.1        }
1337               
1338                     if (velocity_correction) 
1339                     {
1340                        obs_vr = drms_getkey_double(inrec, "OBS_VR", &status);
1341 tplarson 1.8           ParameterDef(status, "OBS_VR", 0.0, &obs_vr, inrec->recnum, 1);
1342 tplarson 1.1  
1343                        obs_vw = drms_getkey_double(inrec, "OBS_VW", &status);
1344 tplarson 1.8           ParameterDef(status, "OBS_VW", 0.0, &obs_vw, inrec->recnum, 1);
1345 tplarson 1.1  
1346                        obs_vn = drms_getkey_double(inrec, "OBS_VN", &status);
1347 tplarson 1.8           ParameterDef(status, "OBS_VN", 0.0, &obs_vn, inrec->recnum, 1);
1348 tplarson 1.1        }
1349               
1350                     // MDI keyword was OBS_DIST, in AU
1351 tplarson 1.21       obsdist = drms_getkey_double(inrec, "DSUN_OBS", &status) / AU;
1352                     // 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 
1353                     ParameterDef(status, "OBS_DIST", 1.0, &obsdist, inrec->recnum, 1);
1354                     if (readrsunref)
1355                     {
1356                       rsunref = drms_getkey_double(inrec, "RSUN_REF", &status);
1357                       ParameterDef(status, "RSUN_REF", RTRUE, &rsunref, inrec->recnum, 1);
1358                       rtrue=rsunref/AU;
1359                     }
1360                     S = rtrue / obsdist; // radians - approx. arcsin(rtrue/obsdist), but don't undo this approximation, because it is assumed in obs2helio
1361 tplarson 1.1  
1362 tplarson 1.21       rsunobs = drms_getkey_double(inrec, "RSUN_OBS", &status);
1363 tplarson 1.9        if (status == DRMS_SUCCESS) 
1364 tplarson 1.21         rsun = rsunobs/imagescale;  //this calculation of rsun assumes approximation of imagescale mentioned in comment above
1365 tplarson 1.9        else
1366                     {
1367                       rsun = drms_getkey_double(inrec, "R_SUN", &status);
1368                       if (status != DRMS_SUCCESS)
1369                         rsun = ARCSECSINRAD * S / sqrt(1.0 - S * S) / imagescale;	   
1370                     }
1371               
1372 tplarson 1.1        if (longitude_shift == 1) 
1373                     {
1374                        tmearth = tobs+TAU_A*(1.0-obsdist); 
1375                        longshift = (obsl0-refl0)+longrate*(tmearth-tref); // degrees 
1376                        while (longshift > 180.0) longshift-=360.0; 
1377                        while (longshift < -180.0) longshift+=360.0;
1378                     }
1379                     else if (longitude_shift == 2) // Shift center to nearest Carrington Degree 
1380                     {
1381                        longshift =  obsl0 - (int)(obsl0);
1382                        if (longshift > 0.5) longshift -= 1.0;
1383                     }
1384                     else if (longitude_shift == 3)  // Shift center to nearest tenth of a degree 
1385                     {
1386                        longshift = (obsl0 * 10 - (int)(obsl0 * 10)) / 10;
1387                        if (longshift > 0.5) longshift -= 1.0;
1388                     }
1389                     else
1390                     {
1391                        longshift = 0.0;
1392                     }
1393 tplarson 1.1  
1394                     mapl0 = obsl0 - longshift;
1395               
1396                     xpixels = inarr->axis[0];
1397                     ypixels = inarr->axis[1];
1398                     pixels  = xpixels * ypixels;
1399               
1400                     // MDI keyword was X0
1401                     x0 = drms_getkey_double(inrec, "CRPIX1", &status);
1402 tplarson 1.8        ParameterDef(status, "CRPIX1", xpixels / 2, &x0, inrec->recnum, 1);
1403 tplarson 1.1        x0 -= 1.0;
1404               
1405                     // MDI keyword was Y0
1406                     y0 = drms_getkey_double(inrec, "CRPIX2", &status);
1407 tplarson 1.8        ParameterDef(status, "CRPIX2", ypixels / 2, &y0, inrec->recnum, 1);
1408 tplarson 1.1        y0 -= 1.0;
1409               
1410                     if (mag_offset) 
1411                     {
1412                       float *dat = (float *)inarr->data;
1413                       double bfitzero = drms_getkey_double(inrec, "BFITZERO", &status);
1414                       PARAMETER_ERROR("BFITZERO")
1415                       int i;
1416               
1417                       if (!isnan(bfitzero)) 
1418                       {
1419                         for (i = 0; i < pixels; ++i) 
1420                         {
1421                           dat[i] -= (float)bfitzero;
1422                         }
1423               
1424                       }
1425                     }
1426               
1427                     if (checko)
1428                     {
1429 tplarson 1.1          orientation = drms_getkey_string(inrec, "ORIENT", &status);
1430                       PARAMETER_ERROR("ORIENT")
1431                       CheckO(orientation, &vstat);
1432                       if (vstat != V2HStatus_Success)
1433                       { 
1434 tplarson 1.8            fprintf(stderr,"ERROR: illegal ORIENT: T_REC = %s, recnum = %lld\n", trecstr, inrec->recnum);
1435 tplarson 1.1            drms_free_array(inarr);
1436                         free(orientation);
1437 tplarson 1.4            error++;
1438 tplarson 1.8            goto continue_outer_loop;
1439 tplarson 1.1          }
1440                     }
1441                     else
1442                     {
1443                        orientation = strdup(orientationdef);
1444                     }
1445               
1446 tplarson 1.21       if (status =       obs2helio((float *)inarr->data, 
1447 tplarson 1.1  	  			   v2hptr,
1448               				   xpixels, 
1449               				   ypixels, 
1450               				   x0, 
1451               				   y0, 
1452               				   b0 * RADSINDEG, 
1453               				   p * RADSINDEG, 
1454               				   S, 
1455               				   rsun, 
1456               				   rmax,
1457               				   interpolation, 
1458               				   mapcols, 
1459               				   maprows, 
1460               				   longmin_adjusted * RADSINDEG, 
1461               				   longinterval * RADSINDEG,
1462               				   longshift * RADSINDEG, 
1463               				   sinBdelta, 
1464               				   smajor, 
1465               				   sminor, 
1466               				   sangle * RADSINDEG, 
1467               				   xscale, 
1468 tplarson 1.1  				   yscale, 
1469               				   orientation, 
1470               				   mag_correction,
1471               				   velocity_correction, 
1472               				   obs_vr, 
1473               				   obs_vw, 
1474               				   obs_vn, 
1475               				   vsign, 
1476               				   NaN_beyond_rmax,
1477               				   carrStretch,
1478               				   &distP,
1479               				   diffrotA,
1480               				   diffrotB,
1481               				   diffrotC,
1482               				   NULL,
1483               				   0))
1484                     {
1485 tplarson 1.14         fprintf(stderr, "ERROR: failure in obs2helio: status = %d, T_REC = %s, recnum = %lld\n", status, trecstr, inrec->recnum);
1486 tplarson 1.1          drms_free_array(inarr);
1487                       free(orientation);
1488 tplarson 1.4          error++;
1489 tplarson 1.8          goto continue_outer_loop;
1490 tplarson 1.1        }
1491                     drms_free_array(inarr);
1492                     free(orientation);
1493               
1494                     if (status =      apodize(v2hptr,
1495               				 b0 * RADSINDEG, 
1496               				 mapcols, 
1497               				 maprows,
1498               				 longmin_adjusted * RADSINDEG,
1499               				 longinterval * RADSINDEG,
1500               				 sinBdelta,
1501               				 apodization, 
1502               				 apinner, 
1503               				 apwidth, 
1504               				 apel, 
1505               				 apx, 
1506               				 apy)) 
1507                     { 
1508 tplarson 1.14         fprintf(stderr, "ERROR: failure in apodize: status = %d, T_REC = %s, recnum = %lld\n", status, trecstr, inrec->recnum);
1509 tplarson 1.4          error++;
1510 tplarson 1.8          goto continue_outer_loop;
1511 tplarson 1.1        }
1512               
1513                     if (v2hflag)
1514                     {
1515 tplarson 1.14 //        outrec = drms_create_record(drms_env,  v2hout, lifetime,  &status);
1516                       outrec=v2hrecset->records[iv2hrec++];
1517 tplarson 1.20         drms_copykeys(outrec, inrec, 0, kDRMS_KeyClass_Explicit);
1518 tplarson 1.1          DRMS_Link_t *histlink = hcon_lookup_lower(&outrec->links, histlinkname);
1519                       DRMS_Link_t *srclink = hcon_lookup_lower(&outrec->links, srclinkname);
1520 tplarson 1.14         if (histlink != NULL)
1521 tplarson 1.1            drms_setlink_static(outrec, histlinkname,  histrecnum);
1522 tplarson 1.14         if (srclink != NULL)
1523 tplarson 1.1            drms_setlink_static(outrec, srclinkname,  inrec->recnum);
1524                       if (segoutflag)
1525                         segout = drms_segment_lookup(outrec, segnameout);
1526                       else
1527                         segout = drms_segment_lookupnum(outrec, 0);
1528                       length[0]=mapcols;
1529                       length[1]=maprows;
1530 tplarson 1.8          outarr = drms_array_create(usetype, 2, length, v2hptr, &status);
1531 tplarson 1.22         drms_setkey_int(outrec, "TOTVALS", maprows*mapcols);
1532 tplarson 1.9          set_statistics(segout, outarr, 1);
1533 tplarson 1.16         outarr->bzero=segout->bzero;
1534                       outarr->bscale=segout->bscale;
1535 tplarson 1.8          status=drms_segment_write(segout, outarr, 0);
1536                       free(outarr);
1537               
1538                       if (status != DRMS_SUCCESS)
1539                       {
1540                         fprintf(stderr, "ERROR: problem writing output segment: status = %d, T_REC = %s, input recnum = %lld, histrecnum = %lld\n", status, trecstr, inrec->recnum, histrecnum);
1541                         return 0;
1542                       }
1543               
1544 tplarson 1.15 //        drms_copykey(outrec, inrec, "T_REC");
1545 tplarson 1.1          drms_setkey_int(outrec, "QUALITY", quality);
1546                       drms_setkey_int(outrec, "MAPMMAX", mapped_lmax);
1547                       drms_setkey_int(outrec, "SINBDIVS", sinb_divisions);
1548                       drms_setkey_float(outrec, "CRPIX1", mapcols/2.0 + 0.5);
1549                       drms_setkey_float(outrec, "CRVAL1", mapl0);
1550                       drms_setkey_float(outrec, "CROTA1", 0.0);
1551                       drms_setkey_float(outrec, "CDELT1", longinterval);
1552                       drms_setkey_float(outrec, "CRPIX2", maprows/2.0 + 0.5);
1553                       drms_setkey_float(outrec, "CRVAL2", 0.0);
1554                       drms_setkey_float(outrec, "CROTA2", 0.0);
1555                       drms_setkey_float(outrec, "CDELT2", sinBdelta);
1556                       drms_setkey_string(outrec, "CTYPE1", "CRLN_CEA");
1557                       drms_setkey_string(outrec, "CTYPE2", "CRLT_CEA");
1558                       drms_setkey_string(outrec, "CUNIT1", "deg");
1559                       drms_setkey_string(outrec, "CUNIT2", "sinlat");
1560 tplarson 1.17 
1561 tplarson 1.22 // set keywords for magnetic pipeline
1562                       drms_setkey_float(outrec, "MAPRMAX", rmax);
1563                       drms_setkey_float(outrec, "MAPBMAX", bmax);
1564                       drms_setkey_float(outrec, "MAPLGMAX", longmax_adjusted);
1565                       drms_setkey_float(outrec, "MAPLGMIN", longmin_adjusted);
1566                       drms_setkey_int(outrec, "INTERPO", interpolation);
1567                       drms_setkey_int(outrec, "LGSHIFT", longitude_shift);
1568                       drms_setkey_int(outrec, "MCORLEV", mag_correction);
1569                       drms_setkey_int(outrec, "MOFFSET", mag_offset);
1570                       drms_setkey_int(outrec, "CARSTRCH", carrStretch);
1571                       drms_setkey_float(outrec, "DIFROT_A", diffrotA);
1572                       drms_setkey_float(outrec, "DIFROT_B", diffrotB);
1573                       drms_setkey_float(outrec, "DIFROT_C", diffrotC);
1574               
1575 tplarson 1.1          dsignout=vsign*drms_getkey_double(inrec, "DATASIGN", &status);
1576                       if (status != DRMS_SUCCESS) 
1577                         dsignout=vsign;
1578                       dsignout/=fabs(dsignout);
1579                       drms_setkey_int(outrec, "DATASIGN", (int)dsignout);
1580               
1581                       tnow = (double)time(NULL);
1582                       tnow += UNIX_epoch;
1583                       drms_setkey_time(outrec, "DATE", tnow);
1584               
1585 tplarson 1.14 //        drms_close_record(outrec, DRMS_INSERT_RECORD);
1586 tplarson 1.1        }
1587               
1588               
1589                     if (verbflag > 1) 
1590                     {
1591                       wt=getwalltime();
1592                       ct=getcputime(&ut, &st);
1593                       fprintf(stdout, 
1594                               "    remap done, %.2f ms wall time, %.2f ms cpu time\n", 
1595                               wt-wt2,
1596                               ct-ct2);
1597                     }
1598               
1599 tplarson 1.9        if (!h2mflag && !tsflag)
1600                       goto skip;
1601               
1602 tplarson 1.1        inp=v2hptr;
1603                     outp=h2mptr;
1604               
1605                     mean = 0.0;
1606                     if (subtract_mean)  /* get mean of entire remapped image */
1607                     {
1608                       nmean = 0;
1609                       ip = inp;
1610                       for (row=0; row<maprows; row++)
1611                       {
1612                         for (col=0; col<mapcols; col++) 
1613                         {
1614                           if (!isnan(*ip)) 
1615                           {
1616                             nmean++; 
1617                             mean += *ip;
1618                           }
1619                           ip++;
1620                         }
1621                       }
1622                       mean /= (nmean ? nmean : 1);
1623 tplarson 1.1        }
1624               
1625                     for (row=0; row<maprows; row++) 
1626                     {
1627               
1628                       if (cent_long == 0) 
1629                       {
1630               
1631               /* Old code with 0 at beginning of array */
1632               
1633                         nok = 0; 
1634                         bp = buf; 
1635                         wp = weight;
1636                         ip = inp + mapcols * row;
1637                         for (col=0; col<mapcols; col++) 
1638                         {
1639                           if (!isnan(*ip)) 
1640                           {
1641                             *bp++ = *wp * (*ip - mean);
1642                              nok += 1;
1643                           }
1644 tplarson 1.1              else 
1645                             *bp++ = 0.0;
1646                           ip++;
1647                           wp++;
1648                         }
1649               
1650                         /* zero fill */
1651                         for (i=col; i<nfft; i++)
1652                           *bp++ = 0.0;
1653                       }
1654                       else 
1655                       {
1656               
1657               /* New code with 0 at center meridian */
1658               /* Assumes that input array is symmetric around meridian */
1659               
1660                         nok = 0;
1661               
1662               /* First copy right side of meridian */
1663               
1664                         bp = buf;
1665 tplarson 1.1            ip = inp + mapcols * row+mapcols2;
1666                         wp = weight + mapcols2;
1667                         if (subtract_mean) 
1668                         {
1669                           for (col=0; col<=mapcols2; col++) 
1670                           {
1671                             if (!isnan(*ip)) 
1672                             {
1673                               *bp++ = *wp * (*ip - mean);
1674                               nok += 1;
1675                             }
1676                             else 
1677                               *bp++ = 0.0;
1678                             ip++;
1679                             wp++;
1680                           }
1681                         }
1682                         else 
1683                         {
1684                           for (col=0; col<=mapcols2; col++) 
1685                           {
1686 tplarson 1.1                if (!isnan(*ip)) 
1687                             {
1688                               *bp++ = *wp * *ip;
1689                               nok += 1;
1690                             }
1691                             else 
1692                               *bp++ = 0.0;
1693                             ip++;
1694                             wp++;
1695                           }
1696                         }
1697               
1698               /* Then do left side of meridian */
1699                         bp = buf+lfft-mapcols2;
1700                         ip = inp + mapcols * row;
1701                         wp = weight;
1702                         if (subtract_mean) 
1703                         {
1704                           for (col=0; col<mapcols2; col++) 
1705                           {
1706                             if (!isnan(*ip)) 
1707 tplarson 1.1                {
1708                               *bp++ = *wp * (*ip - mean); 
1709                               nok += 1;
1710                             }
1711                             else 
1712                               *bp++ = 0.0;
1713                             ip++;
1714                             wp++;
1715                           }
1716                         }
1717                         else 
1718                         {
1719                           for (col=0; col<mapcols2; col++) 
1720                           {
1721                             if (!isnan(*ip)) 
1722                             {
1723                               *bp++ = *wp * *ip;
1724                               nok += 1;
1725                             }
1726                             else 
1727                               *bp++ = 0.0;
1728 tplarson 1.1                ip++;
1729                             wp++;
1730                           }
1731                         }
1732               
1733               /* Finally zero fill */
1734                         bp = buf+mapcols2+1;
1735                         for (i=0; i<lfft-mapcols; i++)
1736                           *bp++ = 0.0;
1737               
1738                       } /* End of copying if statement */
1739               
1740                       if ((zero_miss == 0) && (nok != mapcols)) 
1741                       {
1742               
1743               /* Stuff with missing */
1744                         for (i=0; i<nout; i++) 
1745                         {  
1746                           op = outp + i * maprows + row;
1747                           *op = DRMS_MISSING_FLOAT;
1748                         }
1749 tplarson 1.1          }
1750                       else 
1751                       {
1752                         if (normalize) 
1753                           norm = 1./sqrt(2*(double)nfft/nok)/lfft;
1754                         else
1755                           norm = 1./lfft;
1756 tplarson 1.8  
1757 tplarson 1.1              /* Fourier transform */
1758                         fftwf_execute(fftwp);
1759               
1760                           /* transpose, normalize, this is where most time is spent */
1761                           /* First do real part */
1762                         for (i=0; i<nout/2; i++) 
1763                         {  
1764                           op = outp + 2*i * maprows + row;
1765                           *op = wbuf[i]*norm;
1766                         }
1767                           /* Do imaginary part */
1768                           /* Imaginary part of m=0 is 0*/
1769                         *(outp+row+maprows)=0.0;
1770                           /* Use normx to get the complex conjugate */
1771                         normx=-norm;
1772                         for (i=1; i<nout/2; i++) 
1773                         {  
1774                           op = outp + 2*i * maprows + row + maprows;
1775                           *op = wbuf[lfft-i]*normx;
1776                         }
1777               
1778 tplarson 1.1          }
1779                     } /* Next row */
1780               
1781                     if (h2mflag)
1782                     {
1783 tplarson 1.14 //        outrec = drms_create_record(drms_env, h2mout, lifetime, &status);
1784                       outrec=h2mrecset->records[ih2mrec++];
1785 tplarson 1.20         drms_copykeys(outrec, inrec, 0, kDRMS_KeyClass_Explicit);
1786 tplarson 1.1          DRMS_Link_t *histlink = hcon_lookup_lower(&outrec->links, histlinkname);
1787                       DRMS_Link_t *srclink = hcon_lookup_lower(&outrec->links, srclinkname);
1788 tplarson 1.14         if (histlink != NULL)
1789 tplarson 1.1            drms_setlink_static(outrec, histlinkname,  histrecnum);
1790 tplarson 1.14         if (srclink != NULL)
1791 tplarson 1.1            drms_setlink_static(outrec, srclinkname,  inrec->recnum);
1792                       if (segoutflag)
1793                         segout = drms_segment_lookup(outrec, segnameout);
1794                       else
1795                         segout = drms_segment_lookupnum(outrec, 0);
1796                       length[0]=maprows;
1797                       length[1]=nout;
1798 tplarson 1.8          outarr = drms_array_create(usetype, 2, length, h2mptr, &status);
1799 tplarson 1.22         drms_setkey_int(outrec, "TOTVALS", maprows*nout);
1800 tplarson 1.9          set_statistics(segout, outarr, 1);
1801 tplarson 1.16         outarr->bzero=segout->bzero;
1802                       outarr->bscale=segout->bscale;
1803 tplarson 1.8          status=drms_segment_write(segout, outarr, 0);
1804                       free(outarr);
1805               
1806                       if (status != DRMS_SUCCESS)
1807                       {
1808                         fprintf(stderr, "ERROR: problem writing output segment: status = %d, T_REC = %s, input recnum = %lld, histrecnum = %lld\n", status, trecstr, inrec->recnum, histrecnum);
1809                         return 0;
1810                       }
1811               
1812 tplarson 1.15 //        drms_copykey(outrec, inrec, "T_REC");
1813 tplarson 1.1          drms_setkey_int(outrec, "QUALITY", quality);
1814                       drms_setkey_int(outrec, "MAPMMAX", mapped_lmax);
1815                       drms_setkey_int(outrec, "SINBDIVS", sinb_divisions);
1816                       drms_setkey_int(outrec, "LMAX", lmax);
1817                       drms_setkey_double(outrec, "CRPIX1", maprows/2.0 + 0.5);
1818                       drms_setkey_double(outrec, "CRVAL1", 0.0);
1819                       drms_setkey_double(outrec, "CROTA1", 0.0);
1820                       drms_setkey_double(outrec, "CDELT1", sinBdelta);
1821                       drms_setkey_double(outrec, "CRPIX2", 1.0);
1822                       drms_setkey_double(outrec, "CRVAL2", 0.0);
1823                       drms_setkey_double(outrec, "CROTA2", 0.0);
1824                       drms_setkey_double(outrec, "CDELT2", 1.0);
1825                       drms_setkey_string(outrec, "CTYPE1", "CRLT_CEA");
1826                       drms_setkey_string(outrec, "CTYPE2", "CRLN_FFT");
1827                       drms_setkey_string(outrec, "CUNIT1", "rad");
1828                       drms_setkey_string(outrec, "CUNIT2", "m");
1829 tplarson 1.17 
1830 tplarson 1.1          tnow = (double)time(NULL);
1831                       tnow += UNIX_epoch;
1832                       drms_setkey_time(outrec, "DATE", tnow);
1833 tplarson 1.14 //        drms_close_record(outrec, DRMS_INSERT_RECORD);
1834 tplarson 1.1        }
1835               
1836                     if (verbflag > 1) 
1837                     {
1838                       wt2=getwalltime();
1839                       ct2=getcputime(&ut2, &st2);
1840                       fprintf(stdout, 
1841                               "    fft and transpose done, %.2f ms wall time, %.2f ms cpu time\n", 
1842                               wt2-wt,
1843                               ct2-ct);
1844                     }
1845               
1846 tplarson 1.9        if (!tsflag)
1847                       goto skip;
1848               
1849 tplarson 1.1        inptr=h2mptr;
1850                     imageoffset = imagesize * irec; 
1851                     for (mx = 0; mx < 2*msize; mx++) /* for each m, re and im */
1852                     {
1853                       moffset = mx * maprows;
1854                       mptr = inptr + moffset;
1855                       for (latx = 0; latx < nlat; latx++)
1856                       {
1857                         poslatx = nlat + latx; neglatx = nlat - 1 - latx;
1858                         evenpart[latx] = mptr[poslatx] + mptr[neglatx];
1859                         oddpart[latx] = mptr[poslatx] - mptr[neglatx];   
1860                       }
1861                       workptr = folded + imageoffset + moffset;
1862                       scopy_ (&nlat, evenpart, &increment1, workptr, &increment1);
1863                       workptr += nlat;
1864                       scopy_ (&nlat, oddpart, &increment1, workptr, &increment1);
1865                     }
1866               
1867                     skip:
1868 tplarson 1.8        inrec = drms_recordset_fetchnext(drms_env, inrecset, &fetchstat, &chunkstat, NULL);
1869 tplarson 1.1  
1870 tplarson 1.4        if (inrec != NULL) 
1871 tplarson 1.1        {
1872                       trec = drms_getkey_time(inrec, "T_REC", &status);
1873                       PARAMETER_ERROR("T_REC")
1874 tplarson 1.8          trecind=(trec-tstart+cadence/2)/cadence;
1875 tplarson 1.1          sprint_time(trecstr, trec, "TAI", 0);
1876                     }
1877 tplarson 1.4  
1878 tplarson 1.1  
1879                   } /* end loop on each input image for this timechunk */
1880               
1881                   if (verbflag)
1882                     printf("  number of bad images = %d\n", bc);
1883 tplarson 1.4  
1884 tplarson 1.9      if (!tsflag)
1885                     goto continue_outer_loop;
1886               
1887 tplarson 1.8  //needed if recordset does not extend to end of a timechunk
1888                   while (irec < nrecs)
1889                   {
1890                     bad[bc++]=irec;
1891                     irec++;
1892                   }
1893               
1894 tplarson 1.4      if (bc == nrecs)
1895 tplarson 1.1      {
1896 tplarson 1.4        nodata=1;
1897                   }
1898                   else
1899                   {
1900                     while (bc > 0)
1901                     {
1902                       imageoffset=imagesize*bad[--bc];
1903                       for (i=0;i<imagesize;i++) folded[imageoffset+i]=0.0;
1904                     }
1905 tplarson 1.1      }
1906               
1907                   if (verbflag)
1908                   {
1909                     wt2=getwalltime();
1910                     ct2=getcputime(&ut2, &st2);
1911                     fprintf(stdout, 
1912                               "  images processed, %.2f ms wall time, %.2f ms cpu time\n", 
1913                               wt2-wt1,
1914                               ct2-ct1);
1915                   }
1916               
1917 tplarson 1.8  // skip to here if no input records in a given timechunk
1918                  skip_norecs:  
1919 tplarson 1.1  
1920                  /* we now have folded data for a chunk of sn's */
1921                  /* now do Jesper's tricks */
1922               
1923                  /* ldone is the last l for which plm's have been set up */
1924                   ldone=-1;
1925               
1926                  /* loop on each chunk of l's */
1927                   for (lchunk = lchunkfirst; lchunk <= lchunklast; lchunk++)
1928                   {
1929                     lfirst = lchunk * lchunksize; 
1930                     llast = lfirst + lchunksize - 1;
1931                     lfirst = maxval(lfirst,lmin);
1932                     llast = minval(llast,lmax);
1933                     /* get the first and last indexes into the l-m array */
1934                     ifirst = lfirst*(lfirst+1)/2;
1935                     ilast = llast*(llast+1)/2+llast;
1936               
1937                     if (verbflag > 1) 
1938                     {
1939                       wt3=getwalltime();
1940 tplarson 1.1          ct3=getcputime(&ut3, &st3);
1941                       printf("  processing lchunk %d, lmin = %d, lmax = %d\n", lchunk, lfirst, llast);
1942                     }
1943               
1944 tplarson 1.14 //      outrec = drms_create_record(drms_env, outseries, lifetime, &status);
1945                     outrec=outrecset->records[irecout++];
1946               /*
1947 tplarson 1.1        if (status != DRMS_SUCCESS || outrec == NULL)
1948                     {
1949 tplarson 1.14         fprintf(stderr,"ERROR: unable to open record in output dataseries %s, status = %d, histrecnum = %lld\n", outseries, status, histrecnum);
1950 tplarson 1.1          return 0;
1951                     }
1952 tplarson 1.14 */
1953                     if (histlink != NULL)
1954 tplarson 1.1          drms_setlink_static(outrec, histlinkname,  histrecnum);
1955               
1956 tplarson 1.4        if (nodata)
1957 tplarson 1.8          goto skip_nodata;
1958 tplarson 1.4  
1959 tplarson 1.1        /* now the size of the output array is known */
1960                     length[0]=2*nrecs;           /* accomodate re & im parts for each sn */
1961                     length[1]=(ilast-ifirst+1);  /* for each l & m, lfirst <= l <= llast */
1962               
1963                     outarr = drms_array_create(usetype, 2, length, NULL, &status);
1964               
1965                     if (segoutflag)
1966                       segout = drms_segment_lookup(outrec, segnameout);
1967                     else
1968                       segout = drms_segment_lookupnum(outrec, 0);
1969               
1970 tplarson 1.8        if (segout == NULL || outarr == NULL || status != DRMS_SUCCESS)
1971 tplarson 1.1        {
1972 tplarson 1.14         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", 
1973                                                                                         lfirst, llast, length[0], length[1], status, iset, tstartstr, histrecnum);
1974 tplarson 1.1          return 0; 
1975                     }
1976               
1977                     outptr = (float *)(outarr->data);
1978               
1979                     /* loop on each m */
1980                     for (m = 0; m <= llast; m++)
1981                     {
1982               
1983                       modd = is_odd(m);
1984                       meven = !modd;
1985                       lstart = maxval(lfirst,m); /* no l can be smaller than this m */
1986               
1987                        /* set up masks (plm's) for this m and chunk in l */
1988               
1989                       if ((lstart-1) == ldone)
1990                       {
1991                          /* get saved plms if any */
1992                         if ((lstart - 2) >= m)
1993                           for (latx = 0; latx < nlat; latx++)
1994                             plm[(lstart-2)*nlat + latx] = saveplm[m*nlat + latx];
1995 tplarson 1.1            if ((lstart - 1) >= m)
1996                           for (latx = 0; latx < nlat; latx++)
1997                             plm[(lstart-1)*nlat + latx] = saveplm[msize*nlat + m*nlat + latx];
1998                 
1999                          /* then set up the current chunk */
2000 tplarson 1.17 //          setplm_ (&lstart, &llast, &m, &nlat, indx, latgrid, &nlat, plm); 
2001                         setplm2(lstart, llast, m, nlat, indx, latgrid, nlat, plm, NULL); 
2002 tplarson 1.1          }
2003                       else
2004                       {
2005                        /* This fixes the lmin != 0 problem */
2006 tplarson 1.17 //          setplm_ (&m, &llast, &m, &nlat, indx, latgrid, &nlat, plm);
2007                         setplm2(m, llast, m, nlat, indx, latgrid, nlat, plm, NULL);
2008 tplarson 1.1          }
2009               
2010                        /* save plm's for next chunk */
2011                       if ((llast-1) >= m)
2012                         for (latx = 0; latx < nlat; latx++)
2013                           saveplm[m*nlat + latx] = plm[(llast - 1)*nlat + latx];
2014                       for (latx = 0; latx < nlat; latx++)
2015                         saveplm[msize*nlat + m*nlat + latx] = plm[llast*nlat + latx];
2016                       ldone=llast;
2017               
2018                        /* copy plm's into masks */
2019                        /* note that this converts from double to single precision */
2020                        /* the test prevents underflows which gobble CPU time */
2021               /* Hmmm... looks like if statement is not needed. Weird...
2022                        for (l = lstart; l <= llast; l++) {
2023                           moffset = l * nlat;
2024                           for (latx = 0; latx < nlat; latx++) {
2025                              plmptr = plm + moffset + latx;
2026                              if (is_very_small (*plmptr))
2027                                 masks [(l-lstart)*nlat + latx] = 0.0;
2028                              else
2029 tplarson 1.1                    masks [(l-lstart)*nlat + latx] = *plmptr;
2030                           }
2031                           plmptr = plm + moffset;
2032                           maskptr = masks+(l-lstart)*nlat;
2033                           dscopy_(&nlat,plmptr,maskptr);
2034                        } 
2035               */
2036                       plmptr=plm+nlat*lstart;
2037                       maskptr=masks;
2038                       latx=nlat*(llast-lstart+1);
2039               //        dscopy_(&latx,plmptr,maskptr);
2040                       int ilatx;
2041                       for (ilatx=0;ilatx<latx;ilatx++)
2042                         maskptr[ilatx]=plmptr[ilatx];
2043               
2044                        /* for each sn in snchunk */
2045               //         for (sn = infsn; sn <= inlsn; sn++) {
2046                       for (snx=0; snx<nrecs; snx++)
2047                       {
2048                           /* select folded data for real/imag l's and this m 
2049                              into temporay arrays for matrix multiply */
2050 tplarson 1.1  //            snx = sn - infsn;
2051                           /* TO DO - pull offset calculations out of loop */
2052               /* New code with odd leading dimension */
2053                         scopy_ (&nlat, 
2054                                 folded + nlat*(4*m+modd) + snx*imagesize,
2055                                 &increment1, 
2056                                 real4evenl + snx*nlatx,
2057                                 &increment1);
2058                         scopy_ (&nlat, 
2059                                 folded + nlat*(4*m+meven) + snx*imagesize, 
2060                                 &increment1,
2061                                 real4oddl + snx*nlatx,
2062                                 &increment1);
2063                         scopy_ (&nlat, 
2064                                 folded + nlat*(4*m+2+modd) + snx*imagesize, 
2065                                 &increment1,
2066                                 imag4evenl + snx*nlatx,
2067                                 &increment1);
2068                         scopy_ (&nlat, 
2069                                 folded + nlat*(4*m+2+meven) + snx*imagesize, 
2070                                 &increment1,
2071 tplarson 1.1                    imag4oddl + snx*nlatx,
2072                                 &increment1);
2073                       } /* end loop through snchunk */ 
2074               
2075               
2076                        /* do even l's */
2077                       lfirsteven = is_even(lstart) ? lstart : lstart+1;
2078                       llasteven = is_even(llast) ? llast : llast-1;
2079                       nevenl = (llasteven-lfirsteven)/2 + 1; /* number of even l's */
2080                        /* do real part */
2081                        /* All parts used to have alpha=&one, now have alpha=&cnorm */
2082                       sgemm_ (transpose, /* form of op(A) */ 
2083                               normal,    /* form of op(B) */ 
2084                               &nsn,      /* number of sn's */
2085                               &nevenl,   /* number of even l's for this m */
2086                               &nlat,     /* number of latitudes */
2087                               &cnorm,    /* scalar multiplier of op(A) */
2088                               real4evenl,  /* matrix A */
2089                               &nlatx,     /* use every nlat-long row of A */ 
2090                               masks + nlat*(lfirsteven-lstart), /* matrix B */
2091                               &maprows,  /* 2*nlat, use every other row (nlat long) of B */ 
2092 tplarson 1.1                  &zero,     /* scalar multiplier of C */
2093                               outx + nsn*2*(lfirsteven-lstart), /* matrix C (output) */ 
2094                               &fournsn,  /* use every fourth nsn-long row of C */
2095                               1,         /* length of transpose character string */
2096                               1);        /* length of normal character string */
2097                        /* do imag part */
2098                       sgemm_ (transpose, /* form of op(A) */ 
2099                               normal,    /* form of op(B) */ 
2100                               &nsn,      /* number of sn's */
2101                               &nevenl,   /* number of even l's for this m */
2102                               &nlat,     /* number of latitudes */
2103                               &cnorm,    /* scalar multiplier of op(A) */
2104                               imag4evenl,  /* matrix A */
2105                               &nlatx,     /* use every nlat-long row of A */ 
2106                               masks + nlat*(lfirsteven-lstart), /* matrix B */
2107                               &maprows,  /* 2*nlat, use every other nlat-long row of B */ 
2108                               &zero,     /* scalar multiplier of C */
2109                               outx + nsn*(2*(lfirsteven-lstart)+1), /* matrix C (output) */ 
2110                               &fournsn,  /* use every fourth nsn-long row of C */
2111                               1,         /* length of transpose character string */
2112                               1);        /* length of normal character string */
2113 tplarson 1.1  
2114                        /* do odd l's */
2115                       lfirstodd = is_odd(lstart) ? lstart : lstart+1;
2116                       llastodd = is_odd(llast) ? llast : llast-1; 
2117                       noddl = (llastodd-lfirstodd)/2 + 1; /* number of odd l's */
2118                        /* do real part */
2119                       sgemm_ (transpose, /* form of op(A) */ 
2120                               normal,    /* form of op(B) */ 
2121                               &nsn,      /* number of sn's */
2122                               &noddl,    /* number of odd l's for this m */
2123                               &nlat,     /* number of latitudes */
2124                               &cnorm ,   /* scalar multiplier of op(A) */
2125                               real4oddl,   /* matrix A */
2126                               &nlatx,     /* use every nlat-long row of A */ 
2127                               masks + nlat*(lfirstodd-lstart), /* matrix B */
2128                               &maprows,  /* 2*nlat, use every other nlat-long row of B */ 
2129                               &zero,     /* scalar multiplier of C */
2130                               outx + nsn*2*(lfirstodd-lstart), /* matrix C (output) */ 
2131                               &fournsn,  /* use every fourth nsn-long row of C */
2132                               1,         /* length of transpose character string */
2133                               1);        /* length of normal character string */
2134 tplarson 1.1           /* do imag part */
2135                       sgemm_ (transpose, /* form of op(A) */ 
2136                               normal,    /* form of op(B) */ 
2137                               &nsn,      /* number of sn's */
2138                               &noddl,    /* number of odd l's for this m */
2139                               &nlat,     /* number of latitudes */
2140                               &cnorm,    /* scalar multiplier of op(A) */
2141                               imag4oddl,  /* matrix A */
2142                               &nlatx,     /* use every nlat-long row of A */ 
2143                               masks + nlat*(lfirstodd-lstart), /* matrix B */
2144                               &maprows,  /* 2*nlat, use every other nlat-long row of B */ 
2145                               &zero,     /* scalar multiplier of C */
2146                               outx + nsn*(2*(lfirstodd-lstart)+1), /* matrix C (output) */ 
2147                               &fournsn,  /* use every fourth nsn-long row of C */
2148                               1,         /* length of transpose character string */
2149                               1);        /* length of normal character string */
2150               
2151                        /* copy outx into out sds */
2152                        /* alternate real and imaginary values in out - as in pipeLNU */
2153                       for (l = lstart; l <= llast; l++)
2154                       {
2155 tplarson 1.1            fromoffset = 2*nsn*(l-lstart);
2156                         tooffset = 2*nsn*(l*(l+1)/2 + m -ifirst);
2157                         scopy_ (&nsn,            
2158                                 outx+fromoffset, 
2159                                 &increment1, 
2160                                 outptr+tooffset, 
2161                                 &increment2);
2162                         scopy_ (&nsn, 
2163                                 outx+fromoffset+nsn, 
2164                                 &increment1, 
2165                                 outptr+tooffset+1, 
2166                                 &increment2);
2167                       } /* end loop through l's for this m */
2168               
2169               
2170                     } /* end loop on m */
2171               
2172 tplarson 1.17 
2173 tplarson 1.8        outarr->bzero=segout->bzero;
2174                     outarr->bscale=segout->bscale;
2175                     status=drms_segment_write(segout, outarr, 0);
2176 tplarson 1.4        drms_free_array(outarr);
2177                     nsegments++;
2178               
2179 tplarson 1.8        if (status != DRMS_SUCCESS)
2180                     {
2181                       fprintf(stderr, "ERROR: problem writing output segment: status = %d, T_START = %s, LMIN = %d, LMAX = %d, histrecnum = %lld\n", status, tstartstr, lfirst, llast, histrecnum);
2182                       return 0;
2183                     }
2184               
2185                     skip_nodata:
2186 tplarson 1.4  
2187 tplarson 1.1        drms_setkey_int(outrec, "LMIN", lfirst);
2188                     drms_setkey_int(outrec, "LMAX", llast);
2189                     drms_setkey_time(outrec, "T_START", tstart);
2190                     drms_setkey_time(outrec, "T_STOP", tstart+chunksecs);
2191                     drms_setkey_time(outrec, "T_OBS", tstart+chunksecs/2);
2192                     drms_setkey_time(outrec, "DATE__OBS", tstart);
2193 tplarson 1.8        drms_setkey_string(outrec, "TAG", tag);
2194 tplarson 1.23       if (verflag)
2195                        drms_setkey_string(outrec, "VERSION", version);
2196 tplarson 1.20 
2197                     for (i=0;i<16;i++)
2198                       setbits(calversout,4*i+3,4,nybblearrout[i]);
2199 tplarson 1.16       drms_setkey_longlong(outrec, "CALVER64", calversout);
2200 tplarson 1.1  
2201 tplarson 1.4        if (nodata)
2202                       drms_setkey_int(outrec, "QUALITY", QUAL_NODATA);
2203 tplarson 1.20       else if (mixflag)
2204                       drms_setkey_int(outrec, "QUALITY", QUAL_MIXEDCALVER);
2205 tplarson 1.4        else
2206                       drms_setkey_int(outrec, "QUALITY", 0);
2207 tplarson 1.1  
2208                     // these could be constant, but set them just in case
2209 tplarson 1.6        drms_setkey_int(outrec, "MAPMMAX", mapped_lmax);
2210                     drms_setkey_int(outrec, "SINBDIVS", sinb_divisions);
2211 tplarson 1.1        drms_setkey_float(outrec, "T_STEP", cadence);
2212 tplarson 1.8  
2213 tplarson 1.6        ndt=chunksecs/cadence;
2214                     drms_setkey_int(outrec, "NDT", ndt);
2215               
2216 tplarson 1.1        tnow = (double)time(NULL);
2217                     tnow += UNIX_epoch;
2218                     drms_setkey_time(outrec, "DATE", tnow);
2219               
2220 tplarson 1.14 //      drms_close_record(outrec, DRMS_INSERT_RECORD);
2221 tplarson 1.4        nrecords++;
2222 tplarson 1.1  
2223                     if (verbflag > 1) 
2224                     {
2225                       wt=getwalltime();
2226                       ct=getcputime(&ut, &st);
2227                       fprintf(stdout, 
2228                               "    %.2f ms wall time, %.2f ms cpu time\n", 
2229                               wt-wt3,
2230                               ct-ct3);
2231                     }
2232               
2233               
2234                   } /* end loop on each chunk of l's */
2235               
2236                   if (verbflag)
2237                   {
2238                     wt1=getwalltime();
2239                     ct1=getcputime(&ut1, &st1);
2240                     fprintf(stdout, "SHT of timechunk %d complete: %.2f ms wall time, %.2f ms cpu time\n", iset, 
2241                             wt1-wt2, ct1-ct2);
2242                   }
2243 tplarson 1.1  
2244 tplarson 1.8      continue_outer_loop:
2245 tplarson 1.1      tstart+=chunksecs;
2246                 } /* end loop on each time chunk */
2247               
2248               
2249                 if (chunkstat != kRecChunking_LastInRS && chunkstat != kRecChunking_NoMoreRecs)
2250                   fprintf(stderr, "WARNING: input records remain after last output record: chunkstat = %d\n", (int)chunkstat);
2251               
2252 tplarson 1.8    drms_close_records(inrecset, DRMS_FREE_RECORD);
2253 tplarson 1.14   if (tsflag)
2254                   drms_close_records(outrecset, DRMS_INSERT_RECORD);
2255                 if (v2hflag)
2256                   drms_close_records(v2hrecset, DRMS_INSERT_RECORD);
2257                 if (h2mflag)
2258                   drms_close_records(h2mrecset, DRMS_INSERT_RECORD);
2259               
2260 tplarson 1.1  
2261                 wt=getwalltime();
2262                 ct=getcputime(&ut, &st);
2263 tplarson 1.13   if (verbflag && tsflag) 
2264 tplarson 1.1    {
2265 tplarson 1.4      printf("number of records created  = %d\n", nrecords);
2266                   printf("number of segments created = %d\n", nsegments);
2267 tplarson 1.13   }
2268                 if (verbflag) 
2269                 {
2270 tplarson 1.1      fprintf(stdout, "total time spent: %.2f ms wall time, %.2f ms cpu time\n", 
2271                           wt-wt0, ct-ct0);
2272                 }
2273               
2274 tplarson 1.8    if (!error)
2275                   printf("module %s successful completion\n", cmdparams.argv[0]);
2276                 else
2277                   printf("module %s failed to produce %d timechunks: histrecnum = %lld\n", cmdparams.argv[0], error, histrecnum);
2278               
2279 tplarson 1.1    return 0;
2280               }

Karen Tian
Powered by
ViewCVS 0.9.4