00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <stdio.h>
00043 #include <time.h>
00044 #include <stdlib.h>
00045 #include <string.h>
00046 #include <errno.h>
00047 #include <math.h>
00048 #include <float.h>
00049
00050
00051 #if defined (_WINNT)
00052 #include <direct.h>
00053 #include <io.h>
00054 #elif defined (_SOLARIS)
00055 #include <unistd.h>
00056 #else
00057 #error "_WINNT or _SOLARIS must be set before compiling"
00058 #endif
00059
00060 #include <sys/types.h>
00061 #include <sys/stat.h>
00062
00063 #include "earthworm.h"
00064 #include "trace_buf.h"
00065 #include "swap.h"
00066 #include "ws_clientII.h"
00067 #include "site.h"
00068 #include "time_ew.h"
00069
00070 #include "seihead.h"
00071
00072
00073 static char output_dir [MAX_DIR_LEN];
00074 static char tmp_dirname [MAX_DIR_LEN];
00075 static char network_name [50];
00076 static double start_time;
00077 static double duration;
00078 static int n_channels;
00079 static struct Sei_channel_details *channels;
00080 static struct Sei_channel_details *current_channel;
00081 static FILE *channel_fp;
00082 static int output_native_numbers;
00083 static int tmp_dir_count = 0;
00084
00085
00086 static void write_seisan (FILE *fp, long length, void *data);
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 int open_seisan_file (char *od, char *nn, double st, double dur, int onn)
00106
00107 {
00108
00109
00110 sprintf (tmp_dirname, "%s%c%d_%d_sei.tmp",
00111 od, DIR_DELIM, getpid (), tmp_dir_count ++);
00112 if (CreateDir (tmp_dirname) != EW_SUCCESS) return FALSE;
00113
00114
00115 strcpy (output_dir, od);
00116 strcpy (network_name, nn);
00117 start_time = st;
00118 duration = dur;
00119 n_channels = 0;
00120 channels = current_channel = 0;
00121 output_native_numbers = onn;
00122
00123 return TRUE;
00124
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 int add_seisan_channel (char *chan_name, char *chan_type)
00143
00144 {
00145
00146 struct Sei_channel_details *channel_ptr;
00147
00148
00149
00150 channel_ptr = realloc (channels, sizeof (struct Sei_channel_details) * (n_channels +1));
00151 if (! channel_ptr) return FALSE;
00152 channels = channel_ptr;
00153 n_channels ++;
00154
00155
00156
00157
00158 channel_ptr = channels + n_channels -1;
00159 strcpy (channel_ptr->chan_name, chan_name);
00160 strcpy (channel_ptr->chan_type, chan_type);
00161 channel_ptr->start_time = start_time;
00162 channel_ptr->n_samples = (long) duration;
00163 channel_ptr->n_written = 0;
00164 channel_ptr->sample_rate = 1.0;
00165 channel_ptr->channel_count = n_channels -1;
00166 strcpy (channel_ptr->filename, "");
00167
00168 return TRUE;
00169
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 int start_seisan_channel (char *chan_name, char *chan_type,
00190 double start_time, double sample_rate,
00191 long n_samples)
00192
00193 {
00194
00195 int count;
00196 long value;
00197 struct Sei_channel_details *channel_ptr;
00198
00199
00200
00201
00202
00203 current_channel = 0;
00204 for (count=0, channel_ptr=channels; count<n_channels; count++, channel_ptr++)
00205 {
00206 if ((! strcmp (channel_ptr->chan_name, chan_name)) &&
00207 (! strcmp (channel_ptr->chan_type, chan_type)))
00208 {
00209 current_channel = channel_ptr;
00210 break;
00211 }
00212 }
00213 if (! current_channel) return TRUE;
00214
00215
00216 current_channel->start_time = start_time;
00217 current_channel->sample_rate = sample_rate;
00218 current_channel->n_samples = n_samples;
00219 sprintf (current_channel->filename, "%s%c%d.tmp", tmp_dirname, DIR_DELIM, current_channel->channel_count);
00220
00221
00222 channel_fp = fopen (current_channel->filename, "wb");
00223 if (! channel_fp)
00224 {
00225 strcpy (channel_ptr->filename, "");
00226 return FALSE;
00227 }
00228
00229
00230 value = current_channel->n_samples * sizeof (long);
00231 if (! output_native_numbers) SwapLong (&value);
00232 fwrite (&value, sizeof (long), 1, channel_fp);
00233
00234 return TRUE;
00235
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 void add_seisan_channel_data (long data_len, long *data)
00250
00251 {
00252
00253 int count;
00254 long value;
00255
00256
00257
00258 for (count=0; count<data_len; count++)
00259 {
00260 if (current_channel->n_written >= current_channel->n_samples) break;
00261
00262 value = *(data + count);
00263 if (! output_native_numbers) SwapLong (&value);
00264 fwrite (&value, 4, 1, channel_fp);
00265
00266 current_channel->n_written ++;
00267 }
00268
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 int end_seisan_channel (void)
00284
00285 {
00286
00287 int ret_val;
00288 long value;
00289
00290
00291
00292 value = SEISAN_MISSING_DATA_FLAG;
00293 if (! output_native_numbers) SwapLong (&value);
00294 while (current_channel->n_written < current_channel->n_samples)
00295 {
00296 fwrite (&value, 4, 1, channel_fp);
00297 current_channel->n_written ++;
00298 }
00299
00300
00301 value = current_channel->n_samples * sizeof (long);
00302 if (! output_native_numbers) SwapLong (&value);
00303 fwrite (&value, sizeof (long), 1, channel_fp);
00304
00305
00306 if (ferror (channel_fp)) ret_val = FALSE;
00307 else ret_val = TRUE;
00308 fclose (channel_fp);
00309 return ret_val;
00310
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 int close_seisan_file (void)
00326
00327 {
00328
00329 int channel_count, ret_val, length, end, channel_pos, century_code, count;
00330 long value;
00331 char padded_chan_name [50], padded_network_name [50], sei_filename [MAX_DIR_LEN];
00332 struct Sei_channel_details *channel_ptr;
00333 FILE *sei_fp, *tmp_fp;
00334 time_t ltime;
00335 struct tm conv_time;
00336
00337 static char string [1500];
00338
00339
00340 ret_val = TRUE;
00341
00342
00343 length = strlen (network_name);
00344 for (count=0; count<5; count++)
00345 {
00346 padded_network_name [count] = '_';
00347 if (count < length)
00348 {
00349 if (isprint (*(network_name + count)))
00350 padded_network_name [count] = *(network_name + count);
00351 }
00352 }
00353 padded_network_name [5] = '\0';
00354
00355
00356 ltime = (time_t) start_time;
00357 gmtime_ew (<ime, &conv_time);
00358 sprintf (sei_filename, "%s%c%04d-%02d-%02d-%02d%02d-%02dS.%s_%03d",
00359 output_dir, DIR_DELIM, conv_time.tm_year + 1900, conv_time.tm_mon +1,
00360 conv_time.tm_mday, conv_time.tm_hour, conv_time.tm_min,
00361 conv_time.tm_sec, padded_network_name, n_channels);
00362 sei_fp = fopen (sei_filename, "wb");
00363 if (! sei_fp) return FALSE;
00364
00365
00366 ltime = (time_t) start_time;
00367 gmtime_ew (<ime, &conv_time);
00368 sprintf (string, " %-29.29s%3d%03d %03d %02d %02d %02d %02d %6.3lf %9.3f ",
00369 network_name, n_channels,
00370 conv_time.tm_year, conv_time.tm_yday +1, conv_time.tm_mon +1,
00371 conv_time.tm_mday, conv_time.tm_hour, conv_time.tm_min,
00372 (double) conv_time.tm_sec + (double) ltime - start_time, duration);
00373 write_seisan (sei_fp, 80, string);
00374 memset (string, ' ', 80);
00375 write_seisan (sei_fp, 80, string);
00376
00377
00378 if (n_channels > 30) end = n_channels;
00379 else end = 30;
00380 if (end % 3) end += 3 - (end % 3);
00381 for (channel_count=0, channel_ptr = channels; channel_count<end;
00382 channel_count++, channel_ptr ++)
00383 {
00384 channel_pos = channel_count %3;
00385 if (channel_pos == 0) memset (string, ' ', 80);
00386
00387 if (channel_count < n_channels)
00388 {
00389 strcpy (padded_chan_name, channel_ptr->chan_name);
00390 while (strlen (padded_chan_name) < 5) strcat (padded_chan_name, " ");
00391 sprintf (&string[channel_pos * 26], " %-4.4s%-4.4s%c%7.2f %8.2f",
00392 padded_chan_name, channel_ptr->chan_type, *(padded_chan_name + 4),
00393 channel_ptr->start_time - start_time, channel_ptr->n_samples / channel_ptr->sample_rate);
00394 string [(channel_pos +1) * 26] = ' ';
00395 }
00396
00397 if (channel_pos == 2) write_seisan (sei_fp, 80, string);
00398 }
00399
00400
00401 for (channel_count=0, channel_ptr = channels; channel_count<n_channels;
00402 channel_count++, channel_ptr ++)
00403 {
00404
00405 ltime = (time_t) channel_ptr->start_time;
00406 gmtime_ew (<ime, &conv_time);
00407 century_code = conv_time.tm_year / 100;
00408 sprintf (string, "%-5.5s%-4.4s%d%02d %03d %02d %02d %02d %02d %6.3lf %7.2lf %6ld 4",
00409 channel_ptr->chan_name, channel_ptr->chan_type, century_code, conv_time.tm_year % 100,
00410 conv_time.tm_yday +1, conv_time.tm_mon +1,
00411 conv_time.tm_mday, conv_time.tm_hour, conv_time.tm_min,
00412 ((double) conv_time.tm_sec) + (channel_ptr->start_time - (double) ltime),
00413 channel_ptr->sample_rate, channel_ptr->n_samples);
00414 length = strlen (string);
00415 memset (&string[length], ' ', 1040 - length);
00416 write_seisan (sei_fp, 1040, string);
00417
00418
00419
00420 if (channel_ptr->n_written == channel_ptr->n_samples)
00421 {
00422
00423 tmp_fp = fopen (channel_ptr->filename, "rb");
00424 if (! tmp_fp) ret_val = FALSE;
00425 else
00426 {
00427 while ((length = fread (string, 1, sizeof (string), tmp_fp)) > 0)
00428 fwrite (string, 1, length, sei_fp);
00429 if (ferror (tmp_fp)) ret_val = FALSE;
00430 fclose (tmp_fp);
00431 }
00432 }
00433 else
00434 {
00435
00436
00437 value = channel_ptr->n_samples * sizeof (long);
00438 if (! output_native_numbers) SwapLong (&value);
00439 fwrite (&value, 4, 1, sei_fp);
00440 value = SEISAN_MISSING_DATA_FLAG;
00441 if (! output_native_numbers) SwapLong (&value);
00442 for (count=0; count<channel_ptr->n_samples; count++)
00443 fwrite (&value, 4, 1, sei_fp);
00444 value = channel_ptr->n_samples * sizeof (long);
00445 if (! output_native_numbers) SwapLong (&value);
00446 fwrite (&value, 4, 1, sei_fp);
00447 }
00448
00449
00450 if (channel_ptr->filename [0]) remove (channel_ptr->filename);
00451 }
00452
00453
00454 if (ferror (sei_fp)) ret_val = FALSE;
00455 fclose (sei_fp);
00456
00457
00458 free (channels);
00459 channels = 0;
00460 n_channels = 0;
00461
00462
00463 rmdir (tmp_dirname);
00464
00465
00466 if (! ret_val) remove (sei_filename);
00467
00468 return ret_val;
00469
00470 }
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 static void write_seisan (FILE *fp, long length, void *data)
00487
00488 {
00489
00490 long value;
00491
00492
00493 value = length;
00494 if (! output_native_numbers) SwapLong (&value);
00495 fwrite (&value, 4, 1, fp);
00496 fwrite (data, length, 1, fp);
00497 fwrite (&value, 4, 1, fp);
00498
00499 }
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 int pa_find_data (TRACE_REQ *trace_req, double sample_time,
00541 struct Found_data *data)
00542
00543 {
00544
00545 int bytes_per_sample, data_type_code;
00546 long n_samples, offset;
00547 double start_time, end_time, sample_rate, first_sample_rate;
00548 char *msg_ptr;
00549 TRACE_HEADER *trace_hdr;
00550
00551
00552
00553 first_sample_rate = -1.0;
00554 msg_ptr = trace_req->pBuf;
00555 if (! msg_ptr) return FD_NO_MORE_DATA;
00556 while (msg_ptr < (trace_req->pBuf + trace_req->actLen))
00557 {
00558
00559 trace_hdr = (TRACE_HEADER *) msg_ptr;
00560
00561
00562 if (WaveMsgMakeLocal(trace_hdr) < 0)
00563 {
00564 logit("e", "pa_find_next: unknown trace data type: %s\n",
00565 trace_hdr->datatype);
00566 return( EW_FAILURE );
00567 }
00568
00569 bytes_per_sample = atoi (&trace_hdr->datatype[1]);
00570 n_samples = trace_hdr->nsamp;
00571 start_time = trace_hdr->starttime;
00572 end_time = trace_hdr->endtime;
00573 sample_rate = trace_hdr->samprate;
00574
00575 if (fabs (sample_rate) < 0.000001) sample_rate = 100.0;
00576
00577
00578 if (first_sample_rate < 0.0) first_sample_rate = sample_rate;
00579 else if (sample_rate != first_sample_rate) return FD_CHANGED_SRATE;
00580
00581
00582 switch (trace_hdr->datatype [0])
00583 {
00584 case 's':
00585 case 'i':
00586 switch (bytes_per_sample)
00587 {
00588 case 2: data_type_code = FD_SHORT_INT; break;
00589 case 4: data_type_code = FD_LONG_INT; break;
00590 default: return FD_BAD_DATATYPE;
00591 }
00592 break;
00593 case 't':
00594 case 'f':
00595 switch (bytes_per_sample)
00596 {
00597 case 4: data_type_code = FD_FLOAT; break;
00598 case 8: data_type_code = FD_DOUBLE; break;
00599 default: return FD_BAD_DATATYPE;
00600 }
00601 break;
00602 default:
00603 return FD_BAD_DATATYPE;
00604 }
00605
00606
00607 if ((sample_time >= start_time) && (sample_time <= end_time))
00608 {
00609
00610 offset = (long) (sample_rate * (sample_time - start_time));
00611 data->n_samples = n_samples - offset;
00612 data->data = msg_ptr + sizeof (TRACE_HEADER) + (offset * bytes_per_sample);
00613 data->data_type_code = data_type_code;
00614 data->sample_rate = sample_rate;
00615 data->trace_hdr = trace_hdr;
00616 return FD_FOUND_REQUESTED;
00617 }
00618
00619
00620 if (sample_time < start_time)
00621 {
00622
00623 data->n_samples = (long) (sample_rate * (start_time - sample_time));
00624 data->sample_rate = sample_rate;
00625 return FD_FOUND_GAP;
00626 }
00627
00628
00629 msg_ptr += sizeof (TRACE_HEADER) + (n_samples * bytes_per_sample);
00630 }
00631
00632
00633 return FD_NO_MORE_DATA;
00634
00635 }
00636
00637
00638