/*-------------------------------------------------------------------- * $Id: originator.c,v 1.3.4.2 2002/02/27 17:41:10 pwessel Exp $ * * Copyright (c) 2000-2002 by P. Wessel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Contact info: www.soest.hawaii.edu/wessel *--------------------------------------------------------------------*/ /* * originator reads file of seamount locations and tries to match each * seamount with a probable hotspot by drawing flowines back in time and * keeping track of which hotspot is closest to each flowline. It then * reports the closest hotspot, the stage of the flowline involved, the * implied pseudo-age of the seamount, and the minimum distance between * the flowline and hotspot (in km). * * Author: Paul Wessel, SOEST, Univ. of Hawaii, Honolulu, HI, USA * Date: 29-DEC-1999 * Version: 1.0 * *------------------------------------------------------------------------- * The ASCII Euler file must have following format: * * 1. Any number of comment lines starting with # in first column * 2. Any number of blank lines (just carriage return, no spaces) * 2. Any number of stage pole records which each have the format: * lon(deg) lat(deg) tstart(Ma) tstop(Ma) ccw-angle(deg) * 3. stage records must go from oldest to youngest rotation * 4. Note tstart is larger (older) that tstop for each record * 5. No gaps allowed: tstart must equal the previous records tstop * * Example: Duncan & Clague [1985] Pacific-Hotspot rotations: * * # Time in Ma, angles in degrees * # lon lat tstart tend ccw-angle * 165 85 150 100 24.0 * 284 36 100 74 15.0 * 265 22 74 65 7.5 * 253 17 65 42 14.0 * 285 68 42 0 34.0 * * ASCII seamount location file(s) must have the following format: * * 1. Any number of comment lines starting with # in first column * 2. Any number of blank lines (just carriage return, no spaces) * 3. For special header records, see -H * 4. Any number of data recordswhich each have the format: * lon lat height radius crustal_age (or lat lon ..., see -: option). * crustal_age in Ma, height and radius are not used by originator but * are used by hotspotter. * * Binary files cannot have header records, and data fields must all be * either single or double precision (see -bi option). Output file will * be ASCII since it contains a text string (hotspot ID). * * The file with a list of hotspots must have the following format: * * 1. Any number of comment lines starting with # in first column * 2. Any number of blank lines (just carriage return, no spaces) * 2. Any number of hotspot records which each have the format: * lon(deg) lat(deg) id name * the id is a 3-character tag (e.g., HWI), the name is the * full name of the hotspot (e.g., Hawaii). * * Example: * * # Partial list (Pacific) of HotSpots from Table 1 of Yamaji, 1992 * #Lon Lat Abbreviation Hotspot_name * 167 3 CRL Caroline * 230 46 COB Cobb * 205 20 HWI Hawaii * 221.9 -50.9 LSV Louisville * 220 -29 MDN MacDonald * 221 -11 MRQ Marquesas * 231 -27 PTC Pitcairn * 254 -27 SLG Sala y Gomez * 192 -15 SAM Samoa * 212 -18 SOC Society */ #include "spotter.h" struct HOTSPOT { double lon, lat; /* Current location of hot spot */ double dist; /* Distance to current seamount */ double t; /* Distance to current seamount */ int id; /* Hot spot id flag */ int stage; /* Stage to which seamount belongs */ char name[20]; /* Name of hotspot */ char abbrev[4]; /* 3-char abbreviation of hotspot name */ }; int hotspot_init (char *file, struct HOTSPOT **p); int comp_hs (const void *p1, const void *p2); main (int argc, char **argv) { int i, j, k, n, kk, ns, nh, nc, np, x, y, n_out, fno, n_files = 0, n_args; int n_fields, n_expected_fields, n_read, n_skipped = 0, n_best_hs = 1; BOOLEAN error = FALSE, done, nofile = TRUE, truncate_ages = FALSE, first = TRUE; BOOLEAN finite = FALSE; /* TRUE if stage pole file contains finite rotation poles instead */ double x_smt, y_smt, z_smt, r_smt, t_smt, *c, *in, d_km = 5.0, upper_age = 180.0, dist; double max_dist = 1.0e100; char *hsfile = CNULL, *efile = CNULL, age[32]; FILE *fp; struct EULER *p; struct HOTSPOT *hotspot, *hot; argc = GMT_begin (argc, argv); /* Check command line arguments */ for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { /* Common parameters */ case 'H': case 'V': case ':': case '\0': error += GMT_get_common_args (argv[i], 0, 0, 0, 0); break; /* Supplemental parameters */ case 'b': error += GMT_io_selection (&argv[i][2]); break; case 'C': /* Use finite rotation poles */ finite = TRUE; break; case 'D': d_km = atof (&argv[i][2]); break; case 'E': efile = &argv[i][2]; break; case 'F': hsfile = &argv[i][2]; break; case 'N': upper_age = atof (&argv[i][2]); break; case 'S': n_best_hs = atoi (&argv[i][2]); break; case 'T': truncate_ages = TRUE; break; case 'W': max_dist = atof (&argv[i][2]); break; default: error = TRUE; GMT_default_error (argv[i][1]); break; } } else n_files++; } if (GMT_io.binary[0] && gmtdefs.io_header) { fprintf (stderr, "%s: GMT SYNTAX ERROR. Binary input data cannot have header -H\n", GMT_program); error++; } if (GMT_io.binary[0] && GMT_io.ncol[0] == 0) GMT_io.ncol[0] = 5; if (GMT_io.binary[0] && GMT_io.ncol[0] < 5) { fprintf (stderr, "%s: GMT SYNTAX ERROR. Binary input data (-bi) must have at least 5 columns\n", GMT_program); error++; } if (argc == 1 || GMT_quick) { fprintf (stderr, "%s %s - Associate seamounts with hotspot point sources\n\n", GMT_program, GMT_VERSION); fprintf (stderr, "usage: %s [] -E -F [-C] [-D]\n", GMT_program); fprintf (stderr, " [-H] [-N] [-S] [-T] [-V] [-W] [-:]\n\n"); if (GMT_quick) exit (-1); fprintf (stderr, "\txyfiles is one or more seamount (x,y,z,r,t) files\n"); fprintf (stderr, "\t-E Specify file name for Euler poles.\n"); fprintf (stderr, "\t-F Specify file name for hotspot locations.\n"); fprintf (stderr, "\n\tOPTIONS:\n"); fprintf (stderr, "\t-C The file given with -E contains finite rotation poles [Default is stage poles]\n"); fprintf (stderr, "\t-D set sampling interval in km along tracks [5].\n"); GMT_explain_option ('H'); fprintf (stderr, "\t-N set age (in m.y.) for seafloor where age == NaN [180].\n"); fprintf (stderr, "\t-S Report the closest hotSpots [1].\n"); fprintf (stderr, "\t-T Truncate seamount ages exceeding the upper age set with -N [no truncation] \n"); GMT_explain_option ('V'); fprintf (stderr, "\t-W Only report seamounts whose closest encounter to a hotspot is less than km\n"); fprintf (stderr, "\t [Default reports for all seamounts] \n"); GMT_explain_option (':'); GMT_explain_option ('i'); GMT_explain_option ('n'); fprintf (stderr, " Default is 5 input columns\n"); exit (EXIT_FAILURE); } if (!hsfile) { fprintf (stderr, "%s: GMT SYNTAX ERROR -F: Must specify hotspot file\n", GMT_program); error = TRUE; } if (!efile) { fprintf (stderr, "%s: GMT SYNTAX ERROR -E: Must specify Euler pole file\n", GMT_program); error = TRUE; } if (d_km <= 0.0) { fprintf (stderr, "%s: GMT SYNTAX ERROR -D: Must specify a positive interval\n", GMT_program); error = TRUE; } if (max_dist <= 0.0) { fprintf (stderr, "%s: GMT SYNTAX ERROR -W: Must specify a positive distance in km\n", GMT_program); error = TRUE; } if (error) exit (EXIT_FAILURE); nh = hotspot_init (hsfile, &hotspot); if (n_best_hs <= 0 || n_best_hs > nh) { fprintf (stderr, "%s: GMT SYNTAX ERROR -S: Give value between 1 and %d\n", GMT_program, nh); exit (EXIT_FAILURE); } n_out = MIN (n_best_hs, nh); ns = spotter_init (efile, &p, TRUE, finite, &upper_age); hot = (struct HOTSPOT *) GMT_memory (VNULL, nh, sizeof (struct HOTSPOT), GMT_program); x = (gmtdefs.xy_toggle) ? 1 : 0; y = 1 - x; /* Set up which columns have x and y */ if (n_files > 0) nofile = FALSE; else n_files = 1; n_args = (argc > 1) ? argc : 2; done = FALSE; n_expected_fields = (GMT_io.ncol[0]) ? GMT_io.ncol[0] : 5; n = 0; for (fno = 1; !done && fno < n_args; fno++) { /* Loop over all input files */ if (!nofile && argv[fno][0] == '-') continue; if (nofile) { fp = stdin; done = TRUE; } else if ((fp = GMT_fopen (argv[fno], GMT_io.r_mode)) == NULL) { fprintf (stderr, "%s: Cannot open file %s\n", GMT_program, argv[fno]); continue; } if (!nofile && gmtdefs.verbose) fprintf (stderr, "%s: Working on file %s\n", GMT_program, argv[fno]); n_read = 0; if (gmtdefs.io_header) { for (i = 0; i < gmtdefs.n_header_recs; i++) { GMT_fgets (GMT_io.segment_header, BUFSIZ, fp); if (first && !GMT_io.binary[1]) fprintf (GMT_stdout, "%s", GMT_io.segment_header); n_read++; } first = FALSE; } while ((n_fields = GMT_input (fp, &n_expected_fields, &in)) >= 0 && !(GMT_io.status & GMT_IO_EOF)) { /* Not yet EOF */ n_read++; while ((GMT_io.status & GMT_IO_SEGMENT_HEADER) && !(GMT_io.status & GMT_IO_EOF)) { GMT_write_segmentheader (GMT_stdout, n_expected_fields); n_fields = GMT_input (fp, &n_expected_fields, &in); n_read++; } if (GMT_io.status & GMT_IO_EOF) continue; if (GMT_io.status & GMT_IO_MISMATCH) { fprintf (stderr, "%s: Mismatch between actual (%d) and expected (%d) fields near line %d (skipped)\n", GMT_program, n_fields, n_expected_fields, n_read); continue; } if (GMT_is_dnan (in[4])) { /* Age is NaN, assign value */ t_smt = upper_age; } else { /* Assign given value, truncate if necessary */ t_smt = in[4]; if (t_smt > upper_age) { if (truncate_ages) { t_smt = upper_age; } else { fprintf (stderr, "%s: Seamounts near line %d has age (%lg) > oldest stage (%lg) (skipped)\n", GMT_program, n_read, t_smt, upper_age); continue; } } } if (t_smt < 0.0) { /* Negative ages are flags for points to be skipped */ n_skipped++; continue; } x_smt = in[0] * D2R; y_smt = in[1] * D2R; z_smt = in[2]; r_smt = in[3]; if (gmtdefs.verbose && !(n % 10)) fprintf (stderr, "%s: Working on seamount # %5d\r", GMT_program, n); nc = spotter_forthtrack (&x_smt, &y_smt, &t_smt, 1, p, ns, d_km, 0.0, TRUE, &c); np = (int) c[0]; memcpy ((void *)hot, (void *)hotspot, nh * sizeof (struct HOTSPOT)); for (kk = 0, k = 1; kk < np; kk++, k += 3) { /* For this seamounts track */ for (j = 0; j < nh; j++) { /* For all hotspots */ dist = GMT_great_circle_dist (hot[j].lon, hot[j].lat, R2D * c[k], R2D * c[k+1]) * KM_PR_DEG; if (dist < hot[j].dist) { hot[j].dist = dist; hot[j].t = c[k+2]; } } } for (j = 0; j < nh; j++) { /* Assign stage id */ k = 0; while (k < ns && hot[j].t <= p[k].t_stop) k++; hot[j].stage = ns - k; if (hot[j].stage == 0) hot[j].stage++; } qsort ((void *)hot, nh, sizeof(struct HOTSPOT), comp_hs); if (hot[0].dist < max_dist) { if (t_smt == 180.0) strcpy (age, "NaN"); else sprintf (age, "%lg", t_smt); fprintf (GMT_stdout, "%lg\t%lg\t%lg\t%lg\t%s", in[x], in[y], z_smt, r_smt, age); for (j = 0; j < n_out; j++) fprintf (GMT_stdout, "\t%s\t%d\t%lg\t%lg", hot[j].abbrev, hot[j].stage, hot[j].t, hot[j].dist); fprintf (GMT_stdout, "\n"); } GMT_free ((void *)c); n++; } if (fp != stdin) fclose (fp); } if (gmtdefs.verbose) fprintf (stderr, "%s: Working on seamount # %5d\n", GMT_program, n); GMT_free ((void *)hotspot); GMT_free ((void *)hot); GMT_free ((void *)p); GMT_end (argc, argv); } int comp_hs (const void *p1, const void *p2) { struct HOTSPOT *a, *b; a = (struct HOTSPOT *) p1; b = (struct HOTSPOT *) p2; if (a->dist < b->dist) return (-1); if (a->dist > b->dist) return (1); return (0); } int hotspot_init (char *file, struct HOTSPOT **p) { FILE *fp; struct HOTSPOT *e; char buffer[BUFSIZ]; int i = 0; size_t n_alloc = GMT_CHUNK; if ((fp = fopen (file, "r")) == NULL) { fprintf (stderr, "%s: Cannot open file %s - aborts\n", GMT_program, file); exit (EXIT_FAILURE); } e = (struct HOTSPOT *) GMT_memory (VNULL, n_alloc, sizeof (struct HOTSPOT), GMT_program); while (fgets (buffer, 512, fp) != NULL) { if (buffer[0] == '#' || buffer[0] == '\n') continue; sscanf (buffer, "%lf %lf %s %s", &e[i].lon, &e[i].lat, e[i].abbrev, e[i].name); e[i].id = i; e[i].dist = 1.0e100; i++; if ((size_t)i == n_alloc) { n_alloc += GMT_CHUNK; e = (struct HOTSPOT *) GMT_memory ((void *)e, n_alloc, sizeof (struct HOTSPOT), GMT_program); } } fclose (fp); e = (struct HOTSPOT *) GMT_memory ((void *)e, (size_t)i, sizeof (struct HOTSPOT), GMT_program); *p = e; return (i); }