![]() ![]() |
![]() |
File: [Development] / JSOC / proj / timed / apps / invert_td_hr.c
(download)
Revision: 1.4, Tue Nov 26 00:23:06 2013 UTC (9 years, 6 months ago) by rick Branch: MAIN CVS Tags: Ver_LATEST, Ver_9-5, Ver_9-41, Ver_9-4, Ver_9-3, Ver_9-2, Ver_9-1, Ver_9-0, Ver_8-8, Ver_8-7, Ver_8-6, Ver_8-5, Ver_8-4, Ver_8-3, Ver_8-12, Ver_8-11, Ver_8-10, HEAD Changes since 1.3: +1 -0 lines modified for JSOC release 8.3 |
/* * invert_td_hr.c ~rick/hmi/timed * * Invert travel times from Gabor wavelet and/or Gizon-Birch fitting for * sound-speed and velocity using multichannel deconvolution * * Responsible: Junwei Zhao & Rick Bogart RBogart@solar.stanford.edu * * Usage: * invert_td_hr [-v] in= kernels= out= * * Arguments: (type default description) * in DataSet * copy String "+" Comma separated list of keys to * propagate forward; if the list includes "+", all * keys in the default list of propagation keys, plus * all prime keys in the input records will be copied * * Bugs: * Output array sizes are hardcoded and fixed; no idea what would happen if * input sizes did not match, nor checking to make sure they do * Some assumed key information is hardcoded in Fortran subroutines (e.g. vv) * Only a single input record is processed, though code is very fast, * requiring kernel files to be read repeatedly * Dual processing of travel-time segments from both fitting methods is not * implemented * No documentation * * Notes: * All the work is done by the FORTRAN subroutines inver_cs_sub_() & * inver_v_sub_(), whose arguments are: * inver_cs_sub_() * float *oi_mn input mean out - in (?) travel times * kern *kern_file * name of a FORTRAN unformatted file containing the following vectors * of length n1 * n2 * num_annuli: * float *cs output sound speed values * inver_v_sub_() * float *oi input out - in (?) travel times * float *we input west - east (?) travel times * float *ns input north - south (?) travel times * float *lonc input Stonyhurst longitude of center of region * float *latc input latitude of center of region * kern *kern_file * name of a FORTRAN unformatted file containing the following vectors * of length n1 * n2 * num_annuli: * float *vx output V-west (?) values * float *vy output V-north (?) values * float *vz output V-outward (?) values * int *kerntyp input flag for approximation used in kernel calculation; * currently unused * * Revision history is at end of file. */ #include <jsoc_main.h> #include "keystuff.c" #define KERNTYP_RAY (1) #define KERNTYP_BORN (2) /* module identifier */ char *module_name = "timed_invert"; char *version_id = "0.81"; ModuleArgs_t module_args[] = { {ARG_STRING, "in", "", "input data record"}, {ARG_STRING, "kernels", "", "input kernel"}, {ARG_STRING, "out", "", "output series"}, {ARG_NUME, "fitting", "both", "travel-time fitting method used", "Gabor, GizonBirch, both"}, {ARG_STRING, "copy", "+", "comma separated list of keys to propagate forward"}, {ARG_FLAG, "v", "0", "verbose output"}, {} }; /* list of keywords to propagate (if possible) from input to output */ char *propagate[] = {"CarrRot", "CMLon", "LonHG", "LatHG", "LonCM", "MidTime", "PxLocVer", "WCSAXES", "WCSNAME", "CTYPE1", "CTYPE2", "CRPIX1", "CRPIX2", "CDELT1", "CDELT2", "CUNIT1", "CUNIT2", "CRVAL1", "CRVAL2", "MapScale", "MapProj", "Map_PA"}; extern void inver_cs_sub_ (float *oi_mn, float *kern_cs, float *cs); extern void inver_v_sub_ (float *oi, float *we, float *ns, float *lonc, float *latc, float *kern_vx, float *kern_vy, float *kern_vz, float *vx, float *vy, float *vz, int *kerntyp); enum fittypes {GABOR_WAVELET, GIZON_BIRCH, ALL_FITS}; int DoIt (void) { CmdParams_t *params = &cmdparams; DRMS_RecordSet_t *ids, *kds; DRMS_Record_t *ttrec, *krec, *orec; DRMS_Segment_t *ttseg, *seg_cs, *seg_vx, *seg_vy, *seg_vz; DRMS_Segment_t *kcs_seg, *kvx_seg, *kvy_seg, *kvz_seg; DRMS_Array_t *kcs_arr, *kvx_arr, *kvy_arr, *kvz_arr; DRMS_Array_t *ttdat, *cs_res, *vx_res, *vy_res, *vz_res; float *kcs, *kvx, *kvy, *kvz; float *input, *oi_mn, *oi, *we, *ns, *cs, *vx, *vy, *vz; float *inpmn, *inpoi, *inpwe, *inpns; int *axes; int col, cols, row, rows, pln, pln0, pln1, pln2, pln3; int i, j, k, n, ntot, rgn, rgnct, outok; int pxlocver, kerntyp; int kstat, key_n, propct, propstd, status; char **copykeylist; char *type_segname[] = {"gabor", "GB"}; char *fitting_key[] = {"Gabor", "GizonBirch", "both"}; char *sval; char recid[DRMS_MAXQUERYLEN], source[DRMS_MAXQUERYLEN]; char module_ident[64]; int keyct = sizeof (propagate) / sizeof (char *); int docsinv = 1, dovinv = 1; char *ttimds = strdup (params_get_str (params, "in")); char *kernds = strdup (params_get_str (params, "kernels")); char *outser = strdup (params_get_str (params, "out")); char *propagate_req = strdup (params_get_str (params, "copy")); int fitopt = params_get_int (params, "fitting"); int verbose = params_isflagset (params, "v"); snprintf (module_ident, 64, "%s v %s", module_name, version_id); if (verbose) printf ("%s:\n", module_ident); /* open kernel data record */ kds = drms_open_records (drms_env, kernds, &status); if (status) { fprintf (stderr, "Error: unable to open input record set %s\n", kernds); return 1; } if (kds->n != 1) { fprintf (stderr, "Error: kernel record set %s does not contain single record\n", kernds); drms_close_records (kds, DRMS_FREE_RECORD); return 1; } krec = kds->records[0]; kcs_seg = drms_segment_lookup (krec, "cs"); kvx_seg = drms_segment_lookup (krec, "vx"); kvy_seg = drms_segment_lookup (krec, "vy"); kvz_seg = drms_segment_lookup (krec, "vz"); sval = drms_getkey_string (krec, "Approx", &status); if (status) { fprintf (stderr, "Warning: kernel approximation type not specified in\n"); fprintf (stderr, " %s ; Ray path assumed\n", kernds); kerntyp = KERNTYP_RAY; } else { if (!strcasecmp (sval, "Raypath")) kerntyp = KERNTYP_RAY; else if (!strcasecmp (sval, "Born")) kerntyp = KERNTYP_BORN; else { fprintf (stderr, "Warning: kernel approximation type %s not recognized in\n", sval); fprintf (stderr, " %s ; Ray path assumed\n", kernds); kerntyp = KERNTYP_RAY; } } /* read the kernels */ if (kcs_seg) { kcs_arr = drms_segment_read (kcs_seg, DRMS_TYPE_FLOAT, &status); if (status) { fprintf (stderr, "Warning: unable to read \"cs\" segment in kernel record;\n"); fprintf (stderr, " sound-speed inversions will not be attempted\n"); docsinv = 0; } else kcs = (float *)kcs_arr->data; } else { fprintf (stderr, "Warning: no \"cs\" segment in kernel record;\n"); fprintf (stderr, " sound-speed inversions will not be attempted\n"); docsinv = 0; } if (kvx_seg && kvy_seg && kvz_seg) { kvx_arr = drms_segment_read (kvx_seg, DRMS_TYPE_FLOAT, &status); if (status) dovinv = 0; kvy_arr = drms_segment_read (kvy_seg, DRMS_TYPE_FLOAT, &status); if (status) dovinv = 0; kvz_arr = drms_segment_read (kvz_seg, DRMS_TYPE_FLOAT, &status); if (status) dovinv = 0; if (!dovinv) { fprintf (stderr, "Warning: unable to read one or more v_i segments in kernel record;\n"); fprintf (stderr, " velocity inversions will not be attempted.\n"); if (!docsinv) { fprintf (stderr, " nothing to do!\n"); drms_close_records (kds, DRMS_FREE_RECORD); return 1; } } kvx = (float *)kvx_arr->data; kvy = (float *)kvy_arr->data; kvz = (float *)kvz_arr->data; } else { fprintf (stderr, "Warning: one or more v_i segments missing in kernel record;\n"); fprintf (stderr, " velocity inversions will not be attempted.\n"); if (!docsinv) { fprintf (stderr, " nothing to do!\n"); drms_close_records (kds, DRMS_FREE_RECORD); return 1; } dovinv = 0; } /* open input data series */ ids = drms_open_records (drms_env, ttimds, &status); if (status) { fprintf (stderr, "Error: unable to open input record set %s\n", ttimds); drms_close_records (kds, DRMS_FREE_RECORD); return 1; fprintf (stderr, "input data set is open\n"); } rgnct = ids->n; if (rgnct < 1) { fprintf (stderr, "Error: input dataset %s contains no records\n", ttimds); drms_close_records (kds, DRMS_FREE_RECORD); drms_close_records (ids, DRMS_FREE_RECORD); return 1; } /* allocate input and output arrays */ axes = (int *)malloc (3 * sizeof (int)); cols = axes[0] = rows = axes[1] = 256; axes[2] = 11; ntot = 1; for (n = 0; n < 3; n++) ntot *= axes[n]; oi_mn = (float *)malloc (ntot * sizeof (float)); oi = (float *)malloc (ntot * sizeof (float)); we = (float *)malloc (ntot * sizeof (float)); ns = (float *)malloc (ntot * sizeof (float)); vx = (float *)malloc (ntot * sizeof (float)); vy = (float *)malloc (ntot * sizeof (float)); vz = (float *)malloc (ntot * sizeof (float)); if (docsinv) { cs = (float *)malloc (ntot * sizeof (float)); cs_res = drms_array_create (DRMS_TYPE_FLOAT, 3, axes, cs, &status); if (status) { fprintf (stderr, "Error: unable to create required ouput array cs\n"); return 1; } } vx_res = drms_array_create (DRMS_TYPE_FLOAT, 3, axes, vx, &status); vy_res = drms_array_create (DRMS_TYPE_FLOAT, 3, axes, vy, &status); vz_res = drms_array_create (DRMS_TYPE_FLOAT, 3, axes, vz, &status); outok = 0; rgn = 0; /* read travel times from input record segment "gabor" */ for (rgn = 0; rgn < rgnct; rgn++) { if (verbose) printf ("processing record %d\n", rgn); ttrec = ids->records[rgn]; drms_sprint_rec_query (source, ttrec); /* check PxLocVer, must be consistent with code version */ pxlocver = drms_getkey_int (ttrec, "PxLocVer", &status); if (pxlocver < 1 && verbose) { printf ("Warning: Pixel locator file used for travel time map in record\n"); printf (" %s has unknown version\n", source); } if (fitopt == ALL_FITS) { fprintf (stderr, "Warning: inversions from dual fits not supported\n"); fprintf (stderr, " only Gabor wavelet fits will be used\n"); fitopt = GABOR_WAVELET; } ttseg = drms_segment_lookup (ttrec, type_segname[fitopt]); if (!ttseg) { fprintf (stderr, "Error: no segment \"%s\" in record %s; skipped\n", type_segname[fitopt], source); continue; } ttdat = drms_segment_read (ttseg, DRMS_TYPE_FLOAT, &status); if (!ttdat) { fprintf (stderr, "Error: unable to read input data record-segment in %s\n", source); continue; } input = (float *)ttdat->data; /* create an output record */ orec = drms_create_record (drms_env, outser, DRMS_PERMANENT, &status); if (!orec) { fprintf (stderr, "Error: unable to create record %d in series %s\n", rgn, outser); fprintf (stderr, " remainder of processing skipped\n"); drms_close_records (ids, DRMS_FREE_RECORD); return 0; } seg_cs = drms_segment_lookup (orec, "cs"); seg_vx = drms_segment_lookup (orec, "vx"); seg_vy = drms_segment_lookup (orec, "vy"); seg_vz = drms_segment_lookup (orec, "vz"); /* check the output data series struct (only needs to be done once) */ if (!outok) { /* check for the appropriate segments */ if (!seg_cs) { docsinv = 0; if (!dovinv) { fprintf (stderr, "Error: output data series %s\n", outser); fprintf (stderr, " lacks segment \"cs\", and no flow inversion kernels available\n"); drms_close_records (ids, DRMS_FREE_RECORD); return 1; } fprintf (stderr, "Warning: cs segment missing in output record;\n"); fprintf (stderr, " sound-speed inversions will not be attempted.\n"); } if (!seg_vx) { dovinv = 0; if (!docsinv) { fprintf (stderr, "Error: output data series %s\n", outser); fprintf (stderr, " lacks one or more segments \"vx\", \"vy\", \"vz\"\n"); fprintf (stderr, " and no sound-speed inversion kernels available\n"); drms_close_records (ids, DRMS_FREE_RECORD); return 1; } fprintf (stderr, "Warning: one or more v_i segments missing in output record;\n"); fprintf (stderr, " velocity inversions will not be attempted.\n"); } /* check structure of segments: Fortran code has hard-coded parameters */ if (dovinv) { if (seg_vx->info->naxis != 3 || seg_vy->info->naxis != 3 || seg_vz->info->naxis != 3) { fprintf (stderr, "Error: output data series %s\n", outser); fprintf (stderr, " has wrong rank for one or more segments \"vx\", \"vy\", \"vz\"\n"); drms_close_records (ids, DRMS_FREE_RECORD); return 1; } if (seg_vx->info->scope != DRMS_VARDIM) { if (seg_vx->axis[0] != 256 || seg_vx->axis[1] != 256 || seg_vx->axis[2] != 11) { fprintf (stderr, "Error: in output data series %s\n", outser); fprintf (stderr, " dimensions for segment \"vx\" differ from hard-coded values\n"); drms_close_records (ids, DRMS_FREE_RECORD); return 1; } } if (seg_vy->info->scope != DRMS_VARDIM) { if (seg_vy->axis[0] != 256 || seg_vy->axis[1] != 256 || seg_vy->axis[2] != 11) { fprintf (stderr, "Error: in output data series %s\n", outser); fprintf (stderr, " dimensions for segment \"vy\" differ from hard-coded values\n"); drms_close_records (ids, DRMS_FREE_RECORD); return 1; } } if (seg_vz->info->scope != DRMS_VARDIM) { if (seg_vz->axis[0] != 256 || seg_vz->axis[1] != 256 || seg_vz->axis[2] != 11) { fprintf (stderr, "Error: in output data series %s\n", outser); fprintf (stderr, " dimensions for segment \"vx\" differ from hard-coded values\n"); drms_close_records (ids, DRMS_FREE_RECORD); return 1; } } } if (docsinv) { if (seg_cs->info->naxis != 3) { fprintf (stderr, "Error: output data series %s\n", outser); fprintf (stderr, " has wrong rank for segment \"cs\"\n"); drms_close_records (ids, DRMS_FREE_RECORD); return 1; } if (seg_cs->info->scope != DRMS_VARDIM) { if (seg_cs->axis[0] != 256 || seg_cs->axis[1] != 256 || seg_cs->axis[2] != 11) { fprintf (stderr, "Error: in output data series %s\n", outser); fprintf (stderr, " dimensions for segment \"cs\" differ from hard-coded values\n"); drms_close_records (ids, DRMS_FREE_RECORD); return 1; } } } outok = 1; } /* check input dimensions: Fortran code has hard-coded parameters */ /* copy designated keywords from input to output */ kstat = 0; propct = construct_stringlist (propagate_req, ',', ©keylist); propstd = 0; /* copy specifically requested keys */ for (key_n = 0; key_n < propct; key_n++) { if (strcmp (copykeylist[key_n], "+")) kstat += check_and_copy_key (orec, ttrec, copykeylist[key_n]); else propstd = 1; } if (propstd) { /* copy standard keys */ kstat = propagate_keys (orec, ttrec, propagate, keyct); /* and any additional prime keys */ kstat += copy_prime_keys (orec, ttrec); } kstat += check_and_set_key_str (orec, "Module", module_ident); kstat += check_and_set_key_str (orec, "BLD_VERS", jsoc_version); kstat += check_and_set_key_time (orec, "Created", CURRENT_SYSTEM_TIME); kstat += check_and_set_key_str (orec, "Source", source); kstat += check_and_set_key_str (orec, "Input", ttimds); kstat += check_and_set_key_str (orec, "Kernels", kernds); if (kerntyp == KERNTYP_RAY) kstat += check_and_set_key_str (orec, "KrnAppr", "Raypath"); else if (kerntyp == KERNTYP_BORN) kstat += check_and_set_key_str (orec, "KrnAppr", "Born"); kstat += check_and_set_key_str (orec, "Fitting", fitting_key[fitopt]); if (kstat) { fprintf (stderr, "Error writing key value(s) to record in series %s:\n", outser); fprintf (stderr, " series may not have appropriate structure;\n"); fprintf (stderr, " record %d skipped\n", rgn); drms_close_record (orec, DRMS_FREE_RECORD); continue; } /* use default output scalings */ /* this is a no-op as long as output data are stored as floats */ if (docsinv) { cs_res->bscale = seg_cs->bscale; cs_res->bzero = seg_cs->bzero; } if (dovinv) { vx_res->bscale = seg_vx->bscale; vx_res->bzero = seg_vx->bzero; vy_res->bscale = seg_vy->bscale; vy_res->bzero = seg_vy->bzero; vz_res->bscale = seg_vz->bscale; vz_res->bzero = seg_vz->bzero; } /* need to transpose input array to individual components */ for (k=0; k<11; k++) { pln = k * cols * rows; pln0 = 4 * k * cols * rows; pln1 = (4 * k + 1) * cols * rows; pln2 = (4 * k + 2) * cols * rows; pln3 = (4 * k + 3) * cols * rows; for (row = 0; row < rows; row++){ pln += cols; pln0 += cols; pln1 += cols; pln2 += cols; pln3 += cols; for (col = 0; col < cols; col++){ oi_mn[pln + col] = input[pln0 + col]; oi[pln + col] = input[pln1 + col]; we[pln + col] = input[pln2 + col]; ns[pln + col] = input[pln3 + col]; } } } if (docsinv) inver_cs_sub_ (oi_mn, kcs, cs); if (dovinv) { float latc = drms_getkey_float (ttrec, "LatHG", &status); float lonc = drms_getkey_float (ttrec, "LonCM", &status); inver_v_sub_ (oi, we, ns, &lonc, &latc, kvx, kvy, kvz, vx, vy, vz, &kerntyp); } status = 0; if (docsinv) status += drms_segment_write (seg_cs, cs_res, 0); if (dovinv) { status += drms_segment_write (seg_vx, vx_res, 0); status += drms_segment_write (seg_vy, vy_res, 0); status += drms_segment_write (seg_vz, vz_res, 0); } if (status) { drms_sprint_rec_query (recid, orec); fprintf (stderr, "Error writing data to record %s\n", recid); fprintf (stderr, " series may not have appropriate structure\n"); fprintf (stderr, " record %d skipped\n", rgn); drms_close_record (orec, DRMS_FREE_RECORD); continue; } // fprintf (stderr, "inserting output record\n"); drms_close_record (orec, DRMS_INSERT_RECORD); // fprintf (stderr, "output record inserted\n"); } return 0; } /* * Revision History (all mods by Rick Bogart unless otherwise noted) * * v 0.2 frozen 11.03.11 as working reference * 11.03.12 added verbose flag, some reporting and documentation; travel- * times input from DRMS record set; removed supefluous read fits * function * 11.03.15 output to DRMS * 11.03.18 kernels read from DRMS by driver * v 0.5 frozen 11.03.23 as reference version * 11.03.23 processing of multiple records, some code simplification; * setting of a few keywords; removed include of fftw.f from * mcd_cs_hmi_sub.f in favor of declaration of sole needed * parameter * v 0.6 frozen 11.03.25 * v 0.7 Check version of pixel locator used in travel-time map and * propagate by default * Add arguments for region location to call to inver_v_sub_ * Add argument for kernel type to call to " * Add module argument for fitting method to be used, and setting * of keyword Fitting * Add setting (and checking) of keyword KrnlAppr * Check for existence of required segments in output record, and * modify attempted inversions accordingly; check for agreement of * ouput segment structure with hard-coded dimensions * v 0.8 frozen 2012.08.04 * 12.09.28 added option of adding to or overriding standard list of * keywords from input to output * removed defaults for input and output sets, changed default * fitting method to both * 13.04.08 added WCS keys to propagation list * v 0.81 frozen 2013.04.08 */
Karen Tian |
Powered by ViewCVS 0.9.4 |