ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/JSOC/proj/globalhs/apps/jv2ts.c
Revision: 1.24
Committed: Wed Jan 15 19:08:00 2014 UTC (9 years, 8 months ago) by tplarson
Content type: text/plain
Branch: MAIN
CVS Tags: globalhs_version_5, Ver_8-7, Ver_8-5, Ver_8-3, globalhs_version_8, globalhs_version_2, globalhs_version_3, globalhs_version_4, globalhs_version_6, globalhs_version_7, Ver_8-8, Ver_8-6, Ver_8-4
Changes since 1.23: +4 -5 lines
Log Message:
add MCORLevel2

File Contents

# Content
1 /* this JSOC module is a combination of 3 SOI modules: v2helio, helio2mlat, qdotprod
2 * ported by Tim Larson
3 * removes check on mapbmin, mapbmax, and maprows, these keywords are no longer carried
4 */
5
6 /*
7 * 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 * 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 * 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 * 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 #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 #include "fstats.h"
98 #include "drms_dsdsapi.h"
99 #include "errlog.h"
100 #include "projection.h"
101 #include "atoinc.h"
102
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 //#define AU (1.49597870e11) // this value used in old v2helio
124
125 #define QUAL_NODATA (0x80000000)
126 #define QUAL_MIXEDCALVER (0x00000001)
127 #define kNOTSPECIFIED "not specified"
128
129 char *module_name = "jv2ts";
130 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
132 ModuleArgs_t module_args[] =
133 {
134 // these inputs are common to all modules
135 {ARG_STRING, "in", NULL, "input data records"},
136 {ARG_STRING, "tsout", kNOTSPECIFIED, "output data series"},
137 {ARG_STRING, "segin", kNOTSPECIFIED, "input data segment"},
138 {ARG_STRING, "segout", kNOTSPECIFIED, "output data segment"},
139 {ARG_STRING, "histlink", "HISTORY", "name of link to ancillary dataseries for processing metadata. specify \"none\" to suppress warning messages."},
140 {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 {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 {ARG_STRING, "VERSION", kNOTSPECIFIED, "this parameter sets a keyword of the same name to the same value, useful for selecting obsolete records"},
148 {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 // 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 {ARG_TIME, "TSTART", NULL, "start time of first output record"},
155 {ARG_STRING, "TTOTAL", NULL, "total length of time in output"},
156 {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 {ARG_INT, "ZEROMISS", "0", "zero sets any row containing a NaN to DRMS_MISSING", NULL},
163 {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 {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 {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 {ARG_INT, "MCORLEV", "0", "option for magnetic correction: 0=none; 1=line of sight; 2=radial", ""}, /* 2 levels - see soi_fun.h*/
191 {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 #include "set_history.c"
213 #include "calversfunctions.c"
214
215 int SetDistort(int dist, double cubic, double alpha, double beta, double feff, LIBPROJECTION_Dist_t *dOut);
216
217 int obs2helio(float *V, float *U, int xpixels, int ypixels, double x0, double y0, double BZero, double P,
218 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 const LIBPROJECTION_Dist_t *distpars, float diffrotA, float diffrotB, float diffrotC,
223 LIBPROJECTION_RotRate_t *rRates, int size);
224
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 //char *getshtversion(void);
231
232 /* 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 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 {
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 long long recnum,
280 int verbflag)
281 {
282 /* logs warning and sets parameter to default value */
283 if (status != 0)
284 {
285 *p = defaultp;
286 if (verbflag)
287 fprintf(stderr, "WARNING: default value %g used for %s, status = %d, recnum = %lld\n", defaultp, pname, status, recnum);
288 }
289 }
290
291 #define PARAMETER_ERROR(PNAME) \
292 if (status != DRMS_SUCCESS) \
293 { \
294 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 drms_free_array(inarr); \
296 return 0; \
297 }
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 char *inrecquery = NULL;
307 char *outseries = NULL;
308 char *segnamein = NULL;
309 char *segnameout = NULL;
310 DRMS_RecordSet_t *inrecset = NULL;
311 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 int quality;
331
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 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 double tstart, tepoch, tstep, tround, cadence, nseconds, chunksecs, cadence0;
368 char *ttotal, *tchunk;
369 int nrecs, irec, trecind, bc, iset, ntimechunks;
370 int *bad;
371 int ndt;
372
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 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 double rsunDef, rsunobs;
412 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 LIBPROJECTION_Dist_t distP;
423
424 int errbufstat=setvbuf(stderr, NULL, _IONBF, BUFSIZ);
425 int outbufstat=setvbuf(stdout, NULL, _IONBF, BUFSIZ);
426
427 wt0=getwalltime();
428 ct0=getcputime(&ut0, &st0);
429
430 inrecquery = (char *)cmdparams_save_str(&cmdparams, "in", &newstat);
431 outseries = (char *)cmdparams_save_str(&cmdparams, "tsout", &newstat);
432 int tsflag = strcmp(kNOTSPECIFIED, outseries);
433 segnamein = (char *)cmdparams_save_str(&cmdparams, "segin", &newstat);
434 segnameout = (char *)cmdparams_save_str(&cmdparams, "segout", &newstat);
435 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 int forceoutput = cmdparams_save_int(&cmdparams, "FORCEOUTPUT", &newstat);
444 char *tag = (char *)cmdparams_save_str(&cmdparams, "TAG", &newstat);
445 char *version = (char *)cmdparams_save_str(&cmdparams, "VERSION", &newstat);
446 int verflag = strcmp(kNOTSPECIFIED, version);
447 unsigned short calverkey = (unsigned short)cmdparams_save_int(&cmdparams, "CALVERKEY", &newstat);
448
449 char *histlinkname = (char *)cmdparams_save_str(&cmdparams, "histlink", &newstat);
450 char *srclinkname = (char *)cmdparams_save_str(&cmdparams, "srclink", &newstat);
451
452 char *v2hout = (char *)cmdparams_save_str(&cmdparams, "v2hout", &newstat);
453 char *h2mout = (char *)cmdparams_save_str(&cmdparams, "h2mout", &newstat);
454 int v2hflag = strcmp(kNOTSPECIFIED, v2hout);
455 int h2mflag = strcmp(kNOTSPECIFIED, h2mout);
456 int histflag = strncasecmp("none", histlinkname, 4);
457
458 if (!v2hflag && !h2mflag && !tsflag)
459 {
460 fprintf(stderr, "ERROR: no outputs specified.\n");
461 return 1;
462 }
463
464 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 sprint_time(tstartstr, tstart, "TAI", 0);
471 ttotal=(char *)cmdparams_save_str(&cmdparams, "TTOTAL", &newstat);
472 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 status=drms_names_parseduration(&ttotal, &nseconds, 1);
484 if (status != DRMS_SUCCESS)
485 {
486 fprintf(stderr, "ERROR: problem parsing TTOTAL, = %s\n", ttotal);
487 return 1;
488 }
489 */
490 tchunk=(char *)cmdparams_save_str(&cmdparams, "TCHUNK", &newstat);
491 if (strcmp(kNOTSPECIFIED, tchunk))
492 {
493 chunksecs=atoinc(tchunk);
494 /*
495 status=drms_names_parseduration(&tchunk, &chunksecs, 1);
496 if (status != DRMS_SUCCESS)
497 newstat = newstat | CPSAVE_UNKNOWN_ERROR;
498 */
499 }
500 else if (!tsflag)
501 {
502 fprintf(stderr, "ERROR: TCHUNK must be specified if no tsout is given.\n");
503 return 1;
504 }
505 else
506 chunksecs=0.0;
507
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 int NaN_beyond_rmax = cmdparams_save_int(&cmdparams, "NAN_BEYOND_RMAX", &newstat);
524 int maxmissvals = cmdparams_save_int(&cmdparams, "MAXMISSVALS", &newstat);
525 // float beyondrmax = cmdparams_save_float(&cmdparams, "BEYONDRMAX", &newstat);
526
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 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 // 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 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 if (normflag == 0)
596 cnorm=1.0;
597 else
598 cnorm = sqrt(2.)*sinBdelta;
599
600 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 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 DRMS_Record_t *tempoutrec;
619 DRMS_Link_t *histlink;
620 int itest;
621 /*
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 char *cvsinfo;
624 cvsinfo = (char *)malloc(1024);
625 strcpy(cvsinfo,"$Header: /home/cvsuser/cvsroot/JSOC/proj/globalhs/apps/jv2ts.c,v 1.23 2013/07/02 20:32:03 tplarson Exp $");
626 strcat(cvsinfo,"\n");
627 strcat(cvsinfo,getshtversion());
628 */
629 // 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
639 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 {
653 int sinbdivsout=drms_getkey_int(tempoutrec, "SINBDIVS", &status);
654 if (sinbdivsout != sinb_divisions)
655 {
656 fprintf(stderr,"ERROR: output SINBDIVS=%d does not match input parameter SINBDIVS=%d, status = %d\n", sinbdivsout, sinb_divisions, status);
657 return 1;
658 }
659 }
660
661 // set up ancillary dataseries for processing metadata
662 if (histflag)
663 {
664 histlink = hcon_lookup_lower(&tempoutrec->links, histlinkname);
665 if (histlink != NULL)
666 {
667 histrecnum=set_history(histlink);
668 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 }
679
680 // these must be present in the output dataseries and variable, not links or constants
681 char *outchecklist[] = {"T_START", "QUALITY", "LMIN", "LMAX", "NDT"};
682 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
693 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 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 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 {
709 fprintf(stderr, "ERROR: output dataseries seems incompatible with input parameters (tstep must divide chunksecs): chunksecs = %f, tstep = %f\n", chunksecs, tstep);
710 drms_close_record(tempoutrec, DRMS_FREE_RECORD);
711 return 1;
712 }
713
714 drms_close_record(tempoutrec, DRMS_FREE_RECORD);
715 }
716
717 if (v2hflag)
718 {
719 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 if (histflag && histrecnum < 0)
728 {
729 histlink = hcon_lookup_lower(&tempoutrec->links, histlinkname);
730 if (histlink != NULL)
731 {
732 histrecnum=set_history(histlink);
733 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 }
743 }
744
745 // these must be present in the output dataseries and variable, not links or constants
746 char *outchecklist[] = {"T_REC", "QUALITY", "CRPIX1", "CRVAL1", "CDELT1", "CRPIX2", "CROTA2", "CDELT2" };
747 for (itest=0; itest < ARRLENGTH(outchecklist); itest++)
748 {
749 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 }
757
758 drms_close_record(tempoutrec, DRMS_FREE_RECORD);
759 }
760
761 if (h2mflag)
762 {
763 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 if (histflag && histrecnum < 0)
772 {
773 histlink = hcon_lookup_lower(&tempoutrec->links, histlinkname);
774 if (histlink != NULL)
775 {
776 histrecnum=set_history(histlink);
777 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 }
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 drms_close_record(tempoutrec, DRMS_FREE_RECORD);
803 }
804
805
806 if (fmod(nseconds,chunksecs) != 0.0)
807 {
808 fprintf(stderr, "ERROR: input parameters seem incompatible (chunksecs must divide totalsecs): totalsecs = %f, chunksecs = %f\n", nseconds, chunksecs);
809 return 1;
810 }
811 ntimechunks=nseconds/chunksecs;
812
813 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
820 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 if (inrecset->n == 0)
837 {
838 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 }
842 */
843
844 if (verbflag)
845 printf("input recordset opened, nrecs = %d\n", nrecsin);
846
847 inrec = drms_recordset_fetchnext(drms_env, inrecset, &fetchstat, &chunkstat, NULL);
848
849 // these must be present in the input dataseries
850 char *inchecklist[] = {"T_REC", "QUALITY", "T_OBS", "CRLT_OBS", "CRLN_OBS", "CADENCE",
851 // "SAT_ROT", "INST_ROT", "IM_SCALE",
852 "CDELT1", "CDELT2"};
853
854 DRMS_Keyword_t *inkeytest;
855 for (itest=0; itest < ARRLENGTH(inchecklist); itest++)
856 {
857 inkeytest = hcon_lookup_lower(&inrec->keywords, inchecklist[itest]);
858 if (inkeytest == NULL)
859 {
860 fprintf(stderr, "ERROR: required input keyword %s is missing\n", inchecklist[itest]);
861 drms_close_records(inrecset, DRMS_FREE_RECORD);
862 return 1;
863 }
864 }
865
866 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
880 trec = drms_getkey_time(inrec, "T_REC", &status);
881 if (status != DRMS_SUCCESS)
882 {
883 fprintf(stderr, "ERROR: problem with required parameter T_REC: status = %d, recnum = %lld\n", status, inrec->recnum);
884 drms_close_records(inrecset, DRMS_FREE_RECORD);
885 return 1;
886 }
887 sprint_time(trecstr, trec, "TAI", 0);
888
889 cadence=drms_getkey_float(inrec, "CADENCE", &status);
890 if (status != DRMS_SUCCESS)
891 {
892 fprintf(stderr, "ERROR: problem with required parameter CADENCE: status = %d, T_REC = %s, recnum = %lld\n", status, trecstr, inrec->recnum);
893 drms_close_records(inrecset, DRMS_FREE_RECORD);
894 return 1;
895 }
896
897 if (!forceoutput)
898 {
899 if (nrecsin != nseconds/cadence)
900 {
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
907 if (tsflag && cadence != cadence0)
908 {
909 fprintf(stderr, "ERROR: input CADENCE does not match output T_STEP: status = %d, T_REC = %s, recnum = %lld\n", status, trecstr, inrec->recnum);
910 drms_close_records(inrecset, DRMS_FREE_RECORD);
911 return 1;
912 }
913
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 fprintf(stderr, "ERROR: no records processed: first input record is after last output record: T_REC = %s\n", trecstr);
925 drms_close_records(inrecset, DRMS_FREE_RECORD);
926 return 1;
927 }
928
929 while (trec < tstart && chunkstat != kRecChunking_NoMoreRecs)
930 {
931 fprintf(stderr, "WARNING: input record will not be included in output: T_REC = %s, TSTART = %s \n", trecstr, tstartstr);
932 inrec = drms_recordset_fetchnext(drms_env, inrecset, &fetchstat, &chunkstat, NULL);
933 if (inrec != NULL)
934 {
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 fprintf(stderr,"ERROR: no records processed: last input record is before first output record: T_REC = %s\n", trecstr);
942 drms_close_records(inrecset, DRMS_FREE_RECORD);
943 return 1;
944 }
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 // nlatx=2*(nlat/2)+1;
961
962 /* make nlatx divisible by 4 on linux systems */
963 //#ifdef __linux__
964 if (nlat % 4)
965 nlatx=4*(nlat/4+1);
966 else
967 nlatx=nlat;
968 //#endif
969
970 DRMS_RecordSet_t *outrecset, *v2hrecset, *h2mrecset;
971 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
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 v2hrecset = drms_create_records(drms_env, nrecsin, v2hout, lifetime, &status);
1010 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 h2mrecset = drms_create_records(drms_env, nrecsin, h2mout, lifetime, &status);
1021 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 }
1028
1029
1030 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 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 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
1067 unsigned long long calversout, calvers;
1068 int calversunset=1;
1069 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
1079 int nrecords=0;
1080 int nsegments=0;
1081 int error=0;
1082 int nodata=0;
1083 int irecout=0;
1084 int iv2hrec=0;
1085 int ih2mrec=0;
1086 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 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 }
1111
1112 while (trec < tstart && chunkstat != kRecChunking_NoMoreRecs)
1113 {
1114 inrec = drms_recordset_fetchnext(drms_env, inrecset, &fetchstat, &chunkstat, NULL);
1115 if (inrec != NULL)
1116 {
1117 trec = drms_getkey_time(inrec, "T_REC", &status);
1118 sprint_time(trecstr, trec, "TAI", 0);
1119 }
1120 }
1121
1122 bc=0;
1123 nodata=0;
1124 mixflag=0;
1125 calversunset=1;
1126 trecind=(trec-tstart+cadence/2)/cadence;
1127
1128 for (irec=0; irec < nrecs && chunkstat != kRecChunking_NoMoreRecs; irec++)
1129 {
1130
1131 if (trecind > irec)
1132 //some inputs were missing
1133 {
1134 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 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 }
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 if (verbflag > 2)
1180 fprintf(stderr, "SKIP: image rejected based on quality: T_REC = %s, quality = %08x\n", trecstr, quality);
1181 goto skip;
1182 }
1183
1184 if (tsflag)
1185 {
1186 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 if (status != DRMS_SUCCESS)
1202 calvers = 0;
1203 else
1204 calvers = fixcalver64(calvers);
1205
1206 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
1225 if (!mixflag && calvers != calversout)
1226 mixflag=1;
1227 }
1228
1229
1230 if (seginflag)
1231 segin = drms_segment_lookup(inrec, segnamein);
1232 else
1233 segin = drms_segment_lookupnum(inrec, 0);
1234 if (segin != NULL)
1235 inarr = drms_segment_read(segin, usetype, &status);
1236
1237 if (segin == NULL || inarr == NULL || status != DRMS_SUCCESS)
1238 {
1239 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 }
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 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 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 /*
1272 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 */
1278 double crota = drms_getkey_double(inrec, "CROTA2", &status);
1279 PARAMETER_ERROR("CROTA2")
1280 p=-crota;
1281 }
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 ParameterDef(status, "S_MAJOR", 1.0, &smajor, inrec->recnum, 0);
1294
1295 sminor = drms_getkey_double(inrec, "S_MINOR", &status);
1296 ParameterDef(status, "S_MINOR", 1.0, &sminor, inrec->recnum, 0);
1297
1298 sangle = drms_getkey_double(inrec, "S_ANGLE", &status);
1299 ParameterDef(status, "S_ANGLE", 0.0, &sangle, inrec->recnum, 0);
1300
1301 /*
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 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 fprintf(stderr, "ERROR: CDELT1 != CDELT2 not supported, CDELT1 = %f, CDELT2 = %f: T_REC = %s, recnum = %lld \n", xscale, yscale, trecstr, inrec->recnum);
1315 drms_free_array(inarr);
1316 error++;
1317 goto continue_outer_loop;
1318 }
1319 imagescale=xscale;
1320 xscale=1.0;
1321 yscale=1.0;
1322
1323 /*
1324 imagescale = drms_getkey_double(inrec, "IM_SCALE", &status);
1325 PARAMETER_ERROR("IM_SCALE")
1326 */
1327
1328 if (paramsign != 0)
1329 {
1330 vsign = paramsign;
1331 }
1332 else
1333 {
1334 vsign = drms_getkey_double(inrec, "DATASIGN", &status);
1335 ParameterDef(status, "DATASIGN", 1.0, &vsign, inrec->recnum, 1);
1336 }
1337
1338 if (velocity_correction)
1339 {
1340 obs_vr = drms_getkey_double(inrec, "OBS_VR", &status);
1341 ParameterDef(status, "OBS_VR", 0.0, &obs_vr, inrec->recnum, 1);
1342
1343 obs_vw = drms_getkey_double(inrec, "OBS_VW", &status);
1344 ParameterDef(status, "OBS_VW", 0.0, &obs_vw, inrec->recnum, 1);
1345
1346 obs_vn = drms_getkey_double(inrec, "OBS_VN", &status);
1347 ParameterDef(status, "OBS_VN", 0.0, &obs_vn, inrec->recnum, 1);
1348 }
1349
1350 // MDI keyword was OBS_DIST, in AU
1351 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
1362 rsunobs = drms_getkey_double(inrec, "RSUN_OBS", &status);
1363 if (status == DRMS_SUCCESS)
1364 rsun = rsunobs/imagescale; //this calculation of rsun assumes approximation of imagescale mentioned in comment above
1365 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 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
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 ParameterDef(status, "CRPIX1", xpixels / 2, &x0, inrec->recnum, 1);
1403 x0 -= 1.0;
1404
1405 // MDI keyword was Y0
1406 y0 = drms_getkey_double(inrec, "CRPIX2", &status);
1407 ParameterDef(status, "CRPIX2", ypixels / 2, &y0, inrec->recnum, 1);
1408 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 orientation = drms_getkey_string(inrec, "ORIENT", &status);
1430 PARAMETER_ERROR("ORIENT")
1431 CheckO(orientation, &vstat);
1432 if (vstat != V2HStatus_Success)
1433 {
1434 fprintf(stderr,"ERROR: illegal ORIENT: T_REC = %s, recnum = %lld\n", trecstr, inrec->recnum);
1435 drms_free_array(inarr);
1436 free(orientation);
1437 error++;
1438 goto continue_outer_loop;
1439 }
1440 }
1441 else
1442 {
1443 orientation = strdup(orientationdef);
1444 }
1445
1446 if (status = obs2helio((float *)inarr->data,
1447 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 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 fprintf(stderr, "ERROR: failure in obs2helio: status = %d, T_REC = %s, recnum = %lld\n", status, trecstr, inrec->recnum);
1486 drms_free_array(inarr);
1487 free(orientation);
1488 error++;
1489 goto continue_outer_loop;
1490 }
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 fprintf(stderr, "ERROR: failure in apodize: status = %d, T_REC = %s, recnum = %lld\n", status, trecstr, inrec->recnum);
1509 error++;
1510 goto continue_outer_loop;
1511 }
1512
1513 if (v2hflag)
1514 {
1515 // outrec = drms_create_record(drms_env, v2hout, lifetime, &status);
1516 outrec=v2hrecset->records[iv2hrec++];
1517 drms_copykeys(outrec, inrec, 0, kDRMS_KeyClass_Explicit);
1518 DRMS_Link_t *histlink = hcon_lookup_lower(&outrec->links, histlinkname);
1519 DRMS_Link_t *srclink = hcon_lookup_lower(&outrec->links, srclinkname);
1520 if (histlink != NULL)
1521 drms_setlink_static(outrec, histlinkname, histrecnum);
1522 if (srclink != NULL)
1523 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 outarr = drms_array_create(usetype, 2, length, v2hptr, &status);
1531 drms_setkey_int(outrec, "TOTVALS", maprows*mapcols);
1532 set_statistics(segout, outarr, 1);
1533 outarr->bzero=segout->bzero;
1534 outarr->bscale=segout->bscale;
1535 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 // drms_copykey(outrec, inrec, "T_REC");
1545 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
1561 // 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 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 // drms_close_record(outrec, DRMS_INSERT_RECORD);
1586 }
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 if (!h2mflag && !tsflag)
1600 goto skip;
1601
1602 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 }
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 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 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 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 {
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 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 }
1750 else
1751 {
1752 if (normalize)
1753 norm = 1./sqrt(2*(double)nfft/nok)/lfft;
1754 else
1755 norm = 1./lfft;
1756
1757 /* 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 }
1779 } /* Next row */
1780
1781 if (h2mflag)
1782 {
1783 // outrec = drms_create_record(drms_env, h2mout, lifetime, &status);
1784 outrec=h2mrecset->records[ih2mrec++];
1785 drms_copykeys(outrec, inrec, 0, kDRMS_KeyClass_Explicit);
1786 DRMS_Link_t *histlink = hcon_lookup_lower(&outrec->links, histlinkname);
1787 DRMS_Link_t *srclink = hcon_lookup_lower(&outrec->links, srclinkname);
1788 if (histlink != NULL)
1789 drms_setlink_static(outrec, histlinkname, histrecnum);
1790 if (srclink != NULL)
1791 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 outarr = drms_array_create(usetype, 2, length, h2mptr, &status);
1799 drms_setkey_int(outrec, "TOTVALS", maprows*nout);
1800 set_statistics(segout, outarr, 1);
1801 outarr->bzero=segout->bzero;
1802 outarr->bscale=segout->bscale;
1803 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 // drms_copykey(outrec, inrec, "T_REC");
1813 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
1830 tnow = (double)time(NULL);
1831 tnow += UNIX_epoch;
1832 drms_setkey_time(outrec, "DATE", tnow);
1833 // drms_close_record(outrec, DRMS_INSERT_RECORD);
1834 }
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 if (!tsflag)
1847 goto skip;
1848
1849 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 inrec = drms_recordset_fetchnext(drms_env, inrecset, &fetchstat, &chunkstat, NULL);
1869
1870 if (inrec != NULL)
1871 {
1872 trec = drms_getkey_time(inrec, "T_REC", &status);
1873 PARAMETER_ERROR("T_REC")
1874 trecind=(trec-tstart+cadence/2)/cadence;
1875 sprint_time(trecstr, trec, "TAI", 0);
1876 }
1877
1878
1879 } /* end loop on each input image for this timechunk */
1880
1881 if (verbflag)
1882 printf(" number of bad images = %d\n", bc);
1883
1884 if (!tsflag)
1885 goto continue_outer_loop;
1886
1887 //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 if (bc == nrecs)
1895 {
1896 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 }
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 // skip to here if no input records in a given timechunk
1918 skip_norecs:
1919
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 ct3=getcputime(&ut3, &st3);
1941 printf(" processing lchunk %d, lmin = %d, lmax = %d\n", lchunk, lfirst, llast);
1942 }
1943
1944 // outrec = drms_create_record(drms_env, outseries, lifetime, &status);
1945 outrec=outrecset->records[irecout++];
1946 /*
1947 if (status != DRMS_SUCCESS || outrec == NULL)
1948 {
1949 fprintf(stderr,"ERROR: unable to open record in output dataseries %s, status = %d, histrecnum = %lld\n", outseries, status, histrecnum);
1950 return 0;
1951 }
1952 */
1953 if (histlink != NULL)
1954 drms_setlink_static(outrec, histlinkname, histrecnum);
1955
1956 if (nodata)
1957 goto skip_nodata;
1958
1959 /* 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 if (segout == NULL || outarr == NULL || status != DRMS_SUCCESS)
1971 {
1972 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 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 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 // setplm_ (&lstart, &llast, &m, &nlat, indx, latgrid, &nlat, plm);
2001 setplm2(lstart, llast, m, nlat, indx, latgrid, nlat, plm, NULL);
2002 }
2003 else
2004 {
2005 /* This fixes the lmin != 0 problem */
2006 // setplm_ (&m, &llast, &m, &nlat, indx, latgrid, &nlat, plm);
2007 setplm2(m, llast, m, nlat, indx, latgrid, nlat, plm, NULL);
2008 }
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 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 // 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 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 &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
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 /* 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 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
2173 outarr->bzero=segout->bzero;
2174 outarr->bscale=segout->bscale;
2175 status=drms_segment_write(segout, outarr, 0);
2176 drms_free_array(outarr);
2177 nsegments++;
2178
2179 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
2187 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 drms_setkey_string(outrec, "TAG", tag);
2194 if (verflag)
2195 drms_setkey_string(outrec, "VERSION", version);
2196
2197 for (i=0;i<16;i++)
2198 setbits(calversout,4*i+3,4,nybblearrout[i]);
2199 drms_setkey_longlong(outrec, "CALVER64", calversout);
2200
2201 if (nodata)
2202 drms_setkey_int(outrec, "QUALITY", QUAL_NODATA);
2203 else if (mixflag)
2204 drms_setkey_int(outrec, "QUALITY", QUAL_MIXEDCALVER);
2205 else
2206 drms_setkey_int(outrec, "QUALITY", 0);
2207
2208 // these could be constant, but set them just in case
2209 drms_setkey_int(outrec, "MAPMMAX", mapped_lmax);
2210 drms_setkey_int(outrec, "SINBDIVS", sinb_divisions);
2211 drms_setkey_float(outrec, "T_STEP", cadence);
2212
2213 ndt=chunksecs/cadence;
2214 drms_setkey_int(outrec, "NDT", ndt);
2215
2216 tnow = (double)time(NULL);
2217 tnow += UNIX_epoch;
2218 drms_setkey_time(outrec, "DATE", tnow);
2219
2220 // drms_close_record(outrec, DRMS_INSERT_RECORD);
2221 nrecords++;
2222
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
2244 continue_outer_loop:
2245 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 drms_close_records(inrecset, DRMS_FREE_RECORD);
2253 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
2261 wt=getwalltime();
2262 ct=getcputime(&ut, &st);
2263 if (verbflag && tsflag)
2264 {
2265 printf("number of records created = %d\n", nrecords);
2266 printf("number of segments created = %d\n", nsegments);
2267 }
2268 if (verbflag)
2269 {
2270 fprintf(stdout, "total time spent: %.2f ms wall time, %.2f ms cpu time\n",
2271 wt-wt0, ct-ct0);
2272 }
2273
2274 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 return 0;
2280 }