source: trunk/anuga_core/source/anuga/file/urs_ext.c @ 8879

Last change on this file since 8879 was 8134, checked in by wilsonr, 14 years ago

Fixed error messages.

File size: 27.2 KB
Line 
1/*
2gcc -fPIC -c urs_ext.c -I/usr/include/python2.5 -o urs_ext.o -Wall -O
3gcc -shared urs_ext.o  -o urs_ext.so
4*/
5
6#include "Python.h"
7#include "numpy/arrayobject.h"
8#include "structure.h"
9#include "math.h"
10#include <stdio.h>
11#include <string.h>
12#include <errno.h>
13#include <float.h>
14#include <time.h>
15
16#include "numpy_shim.h"
17
18#define MAX_FILE_NAME_LENGTH 128
19#define NODATA 99.0
20#define EPSILON  0.00001
21
22#define DEBUG 0
23
24#define POFFSET 5 //Number of site_params
25
26static int *fros=NULL;  // First recorded output step
27static int *lros=NULL;  // Last recorded output step
28static struct tgsrwg* mytgs0=NULL;
29
30static long numDataMax=0;
31
32
33/*The MUX file format
34
35
36*/
37
38
39
40/////////////////////////////////////////////////////////////////////////
41//Auxiliary functions
42void fillDataArray(int ista, int total_number_of_stations, int nt, int ig, int *nst, 
43                   int *nft, float *data, int *istart_p, 
44                   int *istop_p, float *muxData)
45{
46    int it, last_it, jsta;
47    long int offset=0;
48
49
50    last_it = -1;
51    /* Make arrays of starting and finishing time steps for the tide gauges */
52    /* and fill them from the file */
53
54    /* Update start and stop timesteps for this gauge */
55    if (nst[ista]!= -1)
56    {
57        if(*istart_p == -1)
58        {
59            *istart_p = nst[ista];
60        }
61        else
62        {
63            *istart_p = ((nst[ista] < *istart_p) ? nst[ista] : *istart_p);
64        }
65    }
66
67    if (nft[ista] != -1)
68    {
69        if (*istop_p == -1)
70        {
71            *istop_p = nft[ista];
72        }
73        else
74        {
75            *istop_p = ((nft[ista] < *istop_p) ? nft[ista] : *istop_p);
76        }
77    }     
78
79    if (ig == -1 || nst[ista] == -1) /* currently ig==-1 => nst[ista]==-1 */
80    {
81        /* gauge never started recording, or was outside of all grids,
82        fill array with 0 */
83        for(it = 0; it < nt; it++)
84        {
85            data[it] = 0.0;
86        }
87    }   
88    else
89    {
90        for(it = 0; it < nt; it++)
91        {
92            last_it = it;
93            /* skip t record of data block */
94            offset++;
95            /* skip records from earlier tide gauges */
96            for(jsta = 0; jsta < ista; jsta++)
97                if(it + 1 >= nst[jsta] && it + 1 <= nft[jsta])
98                    offset++;
99
100            /* deal with the tide gauge at hand */
101            if(it + 1 >= nst[ista] && it + 1 <= nft[ista])
102            {
103                /* gauge is recording at this time */
104                memcpy(data + it, muxData + offset, sizeof(float));
105
106                //printf("%d: muxdata=%f\n", it, muxData[offset]);
107                //printf("data[%d]=%f, offset=%d\n", it, data[it], offset);
108                offset++;
109            }
110            else if (it + 1 < nst[ista])
111            {
112                /* gauge has not yet started recording */
113                data[it] = 0.0;
114            }   
115            else
116                /* gauge has finished recording */
117            {
118                data[it] = NODATA;
119                break;
120            }
121
122            /* skip records from later tide gauges */
123            for(jsta = ista + 1; jsta < total_number_of_stations; jsta++)
124                if(it + 1 >= nst[jsta] && it+1 <= nft[jsta])
125                    offset++;
126        }
127
128        if(last_it < nt - 1)
129            /* the loop was exited early because the gauge had
130            finished recording */
131            for(it = last_it+1; it < nt; it++)
132                data[it] = NODATA;
133    }
134} 
135
136
137char isdata(float x)
138{
139    if(x < NODATA + EPSILON && NODATA < x + EPSILON)
140    {
141        return 0;
142    }
143    else
144    {
145        return 1; 
146    }
147}
148
149
150long getNumData(const int *fros, const int *lros, const int total_number_of_stations)
151/* calculates the number of data in the data block of a mux file */
152/* based on the first and last recorded output steps for each gauge */ 
153{
154    int ista, last_output_step;
155    long numData = 0;
156
157    last_output_step = 0;   
158    for(ista = 0; ista < total_number_of_stations; ista++)
159        if(*(fros + ista) != -1)
160        {
161            numData += *(lros + ista) - *(fros + ista) + 1;
162            last_output_step = (last_output_step < *(lros+ista) ? 
163                *(lros+ista):last_output_step);
164        }   
165        numData += last_output_step*total_number_of_stations; /* these are the t records */
166        return numData;
167}
168
169/////////////////////////////////////////////////////////////////////////
170//Internal Functions
171int _read_mux2_headers(int numSrc, 
172                       char **muxFileNameArray, 
173                       int* total_number_of_stations,
174                       int* number_of_time_steps,
175                       double* delta_t,
176                       //long* numDataMax,
177                       int verbose)
178{
179    FILE *fp;
180    int numsta, i, j;
181    struct tgsrwg *mytgs=0;
182    char *muxFileName;                                                                 
183    char susMuxFileName;
184    long numData;
185    size_t elements_read; // fread return value
186    int block_size;
187
188    /* Allocate space for the names and the weights and pointers to the data*/
189
190    /* Check that the input files have mux2 extension*/
191    susMuxFileName = 0;
192    for(i = 0; i < numSrc; i++)
193    { 
194        muxFileName = muxFileNameArray[i];
195        if(!susMuxFileName && strcmp(muxFileName + strlen(muxFileName) - 4, 
196            "mux2") != 0)
197        {
198            susMuxFileName = 1;
199            break;
200        }
201    }
202
203    if(susMuxFileName)
204    {
205        printf("\n**************************************************************************\n");
206        printf("   WARNING: This program operates only on multiplexed files in mux2 format\n"); 
207        printf("   At least one input file name does not end with mux2\n");
208        printf("   Check your results carefully!\n");
209        printf("**************************************************************************\n\n");
210    }   
211
212    if (verbose)
213    {
214        printf("Reading mux header information\n");
215    }
216
217    // Loop over all sources, read headers and check compatibility
218    for (i = 0; i < numSrc; i++)
219    {
220        muxFileName = muxFileNameArray[i];
221
222        // Open the mux file
223        if((fp = fopen(muxFileName, "rb")) == NULL)
224        {
225            char *err_msg = strerror(errno);
226
227            fprintf(stderr, "cannot open file '%s': %s\n", muxFileName, err_msg);
228            return -1; 
229        }
230
231        if (!i)
232        {
233            elements_read = fread(total_number_of_stations, sizeof(int), 1, fp);
234            if ((int) elements_read == 0 && ferror(fp)){
235                fprintf(stderr, "Error reading total number of stations\n");
236                fclose(fp);
237                return -2;
238            }
239
240            fros = (int*) malloc(*total_number_of_stations*numSrc*sizeof(int));
241            lros = (int*) malloc(*total_number_of_stations*numSrc*sizeof(int));
242
243            mytgs0 = (struct tgsrwg*) malloc(*total_number_of_stations*sizeof(struct tgsrwg));
244            mytgs = (struct tgsrwg*) malloc(*total_number_of_stations*sizeof(struct tgsrwg));
245
246            block_size = *total_number_of_stations*sizeof(struct tgsrwg);
247            elements_read = fread(mytgs0, block_size , 1, fp);
248            if ((int) elements_read == 0 && ferror(fp)){
249                fprintf(stderr, "Error reading mytgs0\n");
250                fclose(fp);
251                return -2;
252            }
253        }
254        else
255        {
256            // Check that the mux files are compatible
257            elements_read = fread(&numsta, sizeof(int), 1, fp);
258            if ((int) elements_read == 0 && ferror(fp)){
259                fprintf(stderr, "Error reading numsta\n");
260                fclose(fp);
261                return -2;
262            }
263
264            if(numsta != *total_number_of_stations)
265            {
266                fprintf(stderr,"%s has different number of stations to %s\n", 
267                    muxFileName, 
268                    muxFileNameArray[0]);
269                fclose(fp);
270                return -1;   
271            }
272
273            block_size = numsta*sizeof(struct tgsrwg);
274            elements_read = fread(mytgs, block_size, 1, fp); 
275            if ((int) elements_read == 0 && ferror(fp)){
276                fprintf(stderr, "Error reading mgtgs\n");
277                fclose(fp);
278                return -2;
279            }       
280
281
282            for (j = 0; j < numsta; j++)
283            {
284                if (mytgs[j].dt != mytgs0[j].dt)
285                {
286                    fprintf(stderr, "%s has different sampling rate to %s\n", 
287                        muxFileName, 
288                        muxFileNameArray[0]);
289                    fclose(fp);
290                    return -1;           
291                }   
292                if (mytgs[j].nt != mytgs0[j].nt)
293                {
294                    fprintf(stderr, "%s has different series length to %s\n", 
295                        muxFileName, 
296                        muxFileNameArray[0]);
297                    fclose(fp);
298                    return -1;           
299                }
300
301                if (mytgs[j].nt != mytgs0[0].nt)
302                {
303                    printf("Station 0 has different series length to Station %d\n", j); 
304                }
305            }
306        }
307
308        /* Read the start and stop times for this source */
309        elements_read = fread(fros + i*(*total_number_of_stations), 
310            *total_number_of_stations*sizeof(int), 1, fp);
311        if ((int) elements_read == 0 && ferror(fp)){
312            fprintf(stderr, "Error reading start times\n");
313            fclose(fp);
314            return -3;
315        }           
316
317
318        elements_read = fread(lros + i*(*total_number_of_stations), 
319            *total_number_of_stations*sizeof(int), 1, fp);
320        if ((int) elements_read == 0 && ferror(fp)){
321            fprintf(stderr, "Error reading stop times\n");
322            fclose(fp);
323            return -3;
324        }                     
325
326        /* Compute the size of the data block for this source */
327        numData = getNumData(fros + i*(*total_number_of_stations), 
328            lros + i*(*total_number_of_stations), 
329            (*total_number_of_stations));
330
331        /* Sanity check */
332        if (numData < 0)
333        {
334            fprintf(stderr,"Size of data block appears to be negative!\n");
335            return -1;       
336        }
337
338        if (numDataMax < numData)
339        {
340            numDataMax = numData;
341        }
342
343        fclose(fp);         
344    }
345
346
347    // Store time resolution and number of timesteps   
348    // These are the same for all stations as tested above, so
349    // we take the first one.
350    *delta_t = (double)mytgs0[0].dt;
351    *number_of_time_steps = mytgs0[0].nt;
352
353    free(mytgs);
354
355    return 0; // Succesful execution
356}
357
358
359float** _read_mux2(int numSrc, 
360                   char **muxFileNameArray, 
361                   float *weights, 
362                   double *params, 
363                   int *number_of_stations,
364                   long *permutation,
365                   int verbose)
366{
367    FILE *fp;
368    int total_number_of_stations, i, isrc, ista, k;
369    char *muxFileName;
370    int istart=-1, istop=-1;
371    int number_of_selected_stations;
372    float *muxData=NULL; // Suppress warning
373    long numData;
374    long *perm = NULL;
375    long *permutation_temp = NULL;
376
377    int len_sts_data, error_code;
378    float **sts_data;
379    float *temp_sts_data;
380
381    long int offset;
382
383    int number_of_time_steps, N;
384    double delta_t;
385
386    size_t elements_read;
387
388    // Shorthands pointing to memory blocks for each source
389    int *fros_per_source=NULL;     
390    int *lros_per_source=NULL;         
391
392
393    error_code = _read_mux2_headers(numSrc, 
394        muxFileNameArray, 
395        &total_number_of_stations,
396        &number_of_time_steps,
397        &delta_t,
398        verbose);
399    if (error_code != 0) {
400        printf("urs_ext.c: Internal function _read_mux2_headers failed: Error code = %d\n", 
401            error_code);
402
403        return NULL;
404    }
405
406
407    // Apply rule that an empty permutation file means 'take all stations'
408    // We could change this later by passing in None instead of the empty
409    // permutation.
410    number_of_selected_stations = *number_of_stations; 
411    if (number_of_selected_stations == 0)
412    {
413        number_of_selected_stations = total_number_of_stations; 
414
415        // Return possibly updated number of stations
416        *number_of_stations = total_number_of_stations;     
417
418        // Create the Identity permutation vector
419        permutation_temp = (long *) malloc(number_of_selected_stations*sizeof(long));
420        if (permutation_temp == NULL)
421        {
422            printf("ERROR: Memory for permutation_temp could not be allocated.\n");
423            return NULL;
424        }
425       
426        for (i = 0; i < number_of_selected_stations; i++)
427        {
428            permutation_temp[i] = (long) i; 
429        }
430
431        perm = permutation_temp;
432    }
433    else
434    {
435        perm = permutation;
436    }
437
438    // The params array is used only for passing data back to Python.
439    params[0] = (double) number_of_selected_stations;
440    params[1] = (double) delta_t;
441    params[2] = (double) number_of_time_steps;
442
443    // Make array(s) to hold demuxed data for stations given in the
444    // permutation file
445    sts_data = (float**) malloc(number_of_selected_stations*sizeof(float*));
446    if (sts_data == NULL)
447    {
448        printf("ERROR: Memory for sts_data could not be allocated.\n");
449        return NULL;
450    }
451
452    // For each selected station, allocate space for its data
453    len_sts_data = number_of_time_steps + POFFSET; // Max length of each timeseries?
454    for (i = 0; i < number_of_selected_stations; i++)
455    {
456        // Initialise sts_data to zero
457        sts_data[i] = (float*) calloc(len_sts_data, sizeof(float));
458        if (sts_data[i] == NULL)
459        {
460            printf("ERROR: Memory for sts_data could not be allocated.\n");
461            return NULL;
462        }
463    }
464
465    temp_sts_data = (float*) calloc(len_sts_data, sizeof(float));
466    if (temp_sts_data == NULL)
467    {
468        printf("ERROR: Memory for temp_sts_data could not be allocated.\n");
469        return NULL;
470    }
471
472    muxData = (float*) calloc(numDataMax, sizeof(float));
473    if (temp_sts_data == NULL)
474    {
475        printf("ERROR: Memory for muxData could not be allocated.\n");
476        return NULL;
477    }
478
479    // Loop over all sources
480    for (isrc = 0; isrc < numSrc; isrc++)
481    {
482
483        // Shorthands to local memory
484        fros_per_source = (int*) fros + isrc*total_number_of_stations; 
485        lros_per_source = (int*) lros + isrc*total_number_of_stations;     
486
487
488        // Read in data block from mux2 file
489        muxFileName = muxFileNameArray[isrc];
490        if((fp = fopen(muxFileName, "rb")) == NULL)
491        {
492            fprintf(stderr, "cannot open file %s\n", muxFileName);
493            free(muxData);
494            free(temp_sts_data);
495            free(muxData);
496
497            return NULL;                   
498        }
499
500        if (verbose){
501            printf("Reading mux file %s\n", muxFileName);
502        }
503
504        offset = (long int)sizeof(int) + total_number_of_stations*(sizeof(struct tgsrwg) + 2*sizeof(int));
505        //printf("\n offset %i ", (long int)offset);
506        fseek(fp, offset, 0);
507
508        numData = getNumData(fros_per_source, 
509            lros_per_source, 
510            total_number_of_stations);
511        // Note numData is larger than what it has to be.                   
512        //elements_read = fread(muxData, ((int) numData)*sizeof(float), 1, fp);
513        elements_read = fread(muxData, (size_t) sizeof(float), (size_t) numData, fp); 
514        //printf("\n elements_read  %d, ", (int)elements_read);
515        //printf("\n ferror(fp)  %d, ", (int)ferror(fp));
516        if ((int) elements_read == 0 && ferror(fp)) {
517            fprintf(stderr, "Error reading mux data: %s", strerror(errno));
518            if (errno == EFAULT)        // error 14 in /usr/include/asm-generic/errno-base.h
519            {
520                fprintf(stderr, "NOTE: This error has been seen before in low memory systems with no swap.\n");
521            }
522
523            fclose(fp);
524            free(muxData);
525            free(temp_sts_data);
526            free(muxData);
527
528            return NULL;
529        }       
530
531        fclose(fp); 
532
533        // loop over stations present in the permutation array
534        //     use ista with mux data
535        //     use i with the processed data to be returned         
536        for(i = 0; i < number_of_selected_stations; i++)
537        {               
538
539            ista = (int) perm[i]; // Get global index into mux data 
540
541            // fill the data0 array from the mux file, and weight it
542            fillDataArray(ista, 
543                total_number_of_stations, 
544                number_of_time_steps,
545                mytgs0[ista].ig, // Grid number (if -1 fill with zeros)
546                fros_per_source, 
547                lros_per_source, 
548                temp_sts_data, 
549                &istart, 
550                &istop, 
551                muxData);
552
553            // Weight appropriately and add
554            for(k = 0; k < mytgs0[ista].nt; k++)
555            {
556                if((isdata(sts_data[i][k])) && isdata(temp_sts_data[k]))
557                {
558                    sts_data[i][k] += temp_sts_data[k] * weights[isrc];
559                }
560                else
561                {
562                    sts_data[i][k] = NODATA;
563                }
564                //printf("%d: temp_sts_data[%d]=%f\n", i, k, temp_sts_data[k]);     
565
566            }
567
568
569            // Update metadata (e.g. start time and end time)
570            N = number_of_time_steps;
571
572            if (isrc == 0) {
573                // Assign values for first source
574                sts_data[i][N] = (float)mytgs0[ista].geolat;
575                sts_data[i][N+1] = (float)mytgs0[ista].geolon;
576                sts_data[i][N+2] = (float)mytgs0[ista].z;
577                sts_data[i][N+3] = (float)fros_per_source[ista];
578                sts_data[i][N+4] = (float)lros_per_source[ista];
579            } else {
580                // Update first and last timesteps for subsequent sources
581                if (sts_data[i][N+3] > (float)fros_per_source[ista]) {         
582                    if (verbose) {
583                        printf("Adjusting start time for station %d and source %d",
584                            ista, isrc);
585                        printf(" from %f to %f\n", 
586                            sts_data[i][N+3], 
587                            (float) fros_per_source[ista]); 
588                    }
589                    sts_data[i][N+3] = (float) fros_per_source[ista];
590                }
591
592                if (sts_data[i][N+4] < (float) lros_per_source[ista]) {         
593                    if (verbose) {
594                        printf("Adjusting end time for station %d and source %d",
595                            ista, isrc);
596                        printf(" from %f to %f\n", 
597                            sts_data[i][N+4], 
598                            (float) lros_per_source[ista]); 
599                    }
600                    sts_data[i][N+4] = (float) lros_per_source[ista];
601                }               
602            }
603        }
604    }
605
606    //printf("sts_data[1,8]=%f\n", sts_data[1][8]);
607
608    free(muxData);
609    free(temp_sts_data);
610    free(fros);
611    free(lros);
612    free(mytgs0);
613
614    if (permutation_temp)
615    {
616        free(permutation_temp);
617    }
618
619    return sts_data;
620}
621
622/////////////////////////////////////////////////////////////////////////
623//Python gateways
624PyObject *read_mux2(PyObject *self, PyObject *args)
625{
626    /*Read in mux 2 file
627
628    Python call:
629    read_mux2(numSrc,filenames,weights,file_params,permutation,verbose)
630
631    NOTE:
632    A Python int is equivalent to a C long
633    (this becomes really important on 64 bit architectures)
634
635    A Python double corresponds to a C double
636    */
637
638    PyObject *filenames;
639    PyArrayObject *pyweights;
640    PyArrayObject *file_params;
641    PyArrayObject *permutation;  // Ordering of selected stations   
642    PyArrayObject *pydata;
643    PyObject *fname;
644
645    char **muxFileNameArray;
646    float **cdata;
647    float *weights;
648    int dimensions[2];
649    int numSrc;
650    int verbose;
651    int total_number_of_stations;
652    int number_of_selected_stations;   
653    int nt;
654    double dt;
655    int i;
656    int j;
657    int start_tstep;
658    int finish_tstep;
659    int it;
660    int time;
661    int num_ts;
662
663    // Convert Python arguments to C
664    if (!PyArg_ParseTuple(args, "iOOOOi",
665        &numSrc, &filenames, &pyweights, &file_params, 
666        &permutation, &verbose)) 
667    {
668        PyErr_SetString(PyExc_RuntimeError, 
669            "Input arguments to read_mux2 failed");
670        return NULL;
671    }
672
673    if(!PyList_Check(filenames)) 
674    {
675        PyErr_SetString(PyExc_TypeError, "get_first_elem expects a list");
676        return NULL;
677    }
678
679    if(PyList_Size(filenames) == 0)
680    {
681        PyErr_SetString(PyExc_ValueError, "empty lists not allowed");
682        return NULL;
683    }
684
685    if (pyweights->nd != 1 || pyweights->descr->type_num != PyArray_DOUBLE) 
686    {
687        PyErr_SetString(PyExc_ValueError,
688            "pyweights must be one-dimensional and of type double");
689        return NULL; 
690    }
691
692    if(PyList_Size(filenames) != pyweights->dimensions[0])
693    {
694        PyErr_SetString(PyExc_ValueError, 
695            "Must specify one weight for each filename");
696        return NULL;
697    }
698
699    muxFileNameArray = (char**)malloc(numSrc*sizeof(char*));
700    if (muxFileNameArray == NULL) 
701    {
702        PyErr_SetString(PyExc_ValueError, 
703            "ERROR: Memory for muxFileNameArray could not be allocated.");
704
705        return NULL;
706    }
707
708    for (i = 0; i < numSrc; i++)
709    {
710
711        fname = PyList_GetItem(filenames, i);
712        if (!fname) 
713        {
714            PyErr_SetString(PyExc_ValueError, "filename not a string");
715            free(muxFileNameArray);
716
717            return NULL;
718        }       
719
720        muxFileNameArray[i] = PyString_AsString(fname);
721        if (muxFileNameArray[i] == NULL) 
722        {
723            PyErr_SetString(PyExc_ValueError, 
724                "ERROR: Memory for muxFileNameArray could not be allocated.\n");
725            free(muxFileNameArray);
726
727            return NULL;
728        }
729    }
730
731    if (file_params->nd != 1 || file_params->descr->type_num != PyArray_DOUBLE) 
732    {
733        PyErr_SetString(PyExc_ValueError,
734            "file_params must be one-dimensional and of type double");
735        free(muxFileNameArray);
736
737        return NULL; 
738    }
739
740
741    // Create array for weights which are passed to read_mux2
742    weights = (float*) malloc(numSrc*sizeof(float));
743    if (weights == NULL) 
744    {
745        PyErr_SetString(PyExc_ValueError, 
746            "ERROR: Memory for weights could not be allocated.");
747        free(muxFileNameArray);
748        return NULL;
749    }
750
751
752    for (i = 0; i < numSrc; i++)
753    {
754        weights[i] = (float)(*(double*)(pyweights->data + i*pyweights->strides[0]));
755    }
756
757    // Desired number of stations
758    number_of_selected_stations = (int) permutation->dimensions[0];
759
760    // Read in mux2 data from file
761    cdata = _read_mux2(numSrc, 
762        muxFileNameArray, 
763        weights, 
764        (double*)file_params->data,
765        &number_of_selected_stations, 
766        (long*) permutation->data,
767        verbose);
768
769    if (!cdata) 
770    {
771        PyErr_SetString(PyExc_RuntimeError, "No STS_DATA returned");
772        return NULL;
773    }       
774
775    //Extracting data
776    total_number_of_stations = (int)*((double*)(file_params->data + 0*file_params->strides[0]));
777    dt = *(double*)(file_params->data + 1*file_params->strides[0]);
778    nt = (int)*(double*)(file_params->data + 2*file_params->strides[0]);
779
780
781    // Find min and max start times of all gauges
782    start_tstep = nt + 1;
783    finish_tstep = -1;
784    for (i = 0; i < number_of_selected_stations; i++)
785    {
786        //printf("cdata[%d] start = %f\n", i, (double) cdata[i][nt+3]);
787        // printf("cdata[%d] finish = %f\n", i, (double) cdata[i][nt+4]);   
788
789        if ((int)cdata[i][nt + 3] < start_tstep)
790        {
791            start_tstep = (int)cdata[i][nt + 3];
792        }
793        if ((int)cdata[i][nt + 4] > finish_tstep)
794        {
795            finish_tstep = (int)cdata[i][nt + 4]; 
796        }
797    }
798
799    if ((start_tstep > nt) | (finish_tstep < 0))
800    {
801        printf("ERROR: Gauge data has incorrect start and finish times:\n");
802        printf("   start_tstep = %d, max_number_of_steps = %d\n", 
803            start_tstep, nt);
804        printf("   finish_tstep = %d, min_number_of_steps = %d\n", 
805            finish_tstep, 0);   
806
807        PyErr_SetString(PyExc_ValueError, "Incorrect start and finish times"); 
808
809        free(weights);
810        free(muxFileNameArray);
811        for (i = 0; i < number_of_selected_stations; ++i)
812        {
813            free(cdata[i]);
814        }
815        free(cdata);
816
817        return NULL;
818    }
819
820    if (start_tstep >= finish_tstep)
821    {
822        PyErr_SetString(PyExc_ValueError,
823            "ERROR: Gauge data has non-postive_length");
824        free(weights);
825        free(muxFileNameArray);
826        for (i = 0; i < number_of_selected_stations; ++i)
827        {
828            free(cdata[i]);
829        }
830        free(cdata);
831
832        return NULL;
833    }
834
835    num_ts = finish_tstep - start_tstep + 1;
836    dimensions[0] = number_of_selected_stations;
837    dimensions[1] = num_ts + POFFSET;
838
839    pydata = (PyArrayObject*) anuga_FromDims(2, dimensions, PyArray_DOUBLE);
840    if(pydata == NULL)
841    {
842        PyErr_SetString(PyExc_RuntimeError, 
843            "ERROR: Memory for pydata array could not be allocated.");
844        free(weights);
845        free(muxFileNameArray);
846        for (i = 0; i < number_of_selected_stations; ++i)
847        {
848            free(cdata[i]);
849        }
850        free(cdata);
851
852        return NULL;
853    }
854
855
856    // Each gauge begins and ends recording at different times. When a gauge is
857    // not recording but at least one other gauge is.
858    // Pad the non-recording gauge array with zeros.
859    //printf("\nData put into the cdata array from C code\n");
860    for (i = 0; i < number_of_selected_stations; i++)
861    {
862        time = 0;
863        for (it = 0; it < finish_tstep; it++)
864        {
865            if ((it + 1 >= start_tstep) && (it + 1 <= finish_tstep))
866            {
867                if (it + 1 > (int)cdata[i][nt + 4])
868                {
869                    // This gauge has stopped recording but others are
870                    // still recording
871                    *(double*)(pydata->data + i*pydata->strides[0] 
872                    + time*pydata->strides[1]) = 
873                        0.0;
874                }
875                else
876                {
877                    //printf("cdata[%d][%d] = %f\n", i, it, cdata[i][it]);
878
879                    *(double*)(pydata->data + i*pydata->strides[0] 
880                    + time*pydata->strides[1]) = 
881                        cdata[i][it];
882                }
883                time++;
884            }
885        }
886        // Pass back lat,lon,elevation
887        for (j = 0; j < POFFSET; j++)
888        {
889            *(double*)(pydata->data + i*pydata->strides[0] 
890            + (num_ts + j)*pydata->strides[1]) = 
891                cdata[i][nt + j];
892        }
893    }
894
895    free(weights);
896
897    // Free filename array, but not independent Python strings
898    // FIXME(Ole): Do we need to update a reference counter in this case?
899    free(muxFileNameArray);
900
901    for (i = 0; i < number_of_selected_stations; ++i)
902    {
903        free(cdata[i]);
904    }
905    free(cdata);
906
907    return PyArray_Return(pydata);
908}
909
910//-------------------------------
911// Method table for python module
912//-------------------------------
913static struct PyMethodDef MethodTable[] = {
914    {"read_mux2", read_mux2, METH_VARARGS, "Print out"},
915    {NULL, NULL}
916};
917
918// Module initialisation
919void initurs_ext(void){
920    Py_InitModule("urs_ext", MethodTable);
921
922    import_array(); // Necessary for handling of NumPY structures
923}
Note: See TracBrowser for help on using the repository browser.