source: anuga_core/source/anuga/shallow_water/urs_ext.c @ 7585

Last change on this file since 7585 was 7548, checked in by nariman, 15 years ago

fixed memory leak in read_mux2

File size: 26.9 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\n");
518            fclose(fp);
519            free(muxData);
520            free(temp_sts_data);
521            free(muxData);
522
523            return NULL;
524        }       
525
526        fclose(fp); 
527
528        // loop over stations present in the permutation array
529        //     use ista with mux data
530        //     use i with the processed data to be returned         
531        for(i = 0; i < number_of_selected_stations; i++)
532        {               
533
534            ista = (int) perm[i]; // Get global index into mux data 
535
536            // fill the data0 array from the mux file, and weight it
537            fillDataArray(ista, 
538                total_number_of_stations, 
539                number_of_time_steps,
540                mytgs0[ista].ig, // Grid number (if -1 fill with zeros)
541                fros_per_source, 
542                lros_per_source, 
543                temp_sts_data, 
544                &istart, 
545                &istop, 
546                muxData);
547
548            // Weight appropriately and add
549            for(k = 0; k < mytgs0[ista].nt; k++)
550            {
551                if((isdata(sts_data[i][k])) && isdata(temp_sts_data[k]))
552                {
553                    sts_data[i][k] += temp_sts_data[k] * weights[isrc];
554                }
555                else
556                {
557                    sts_data[i][k] = NODATA;
558                }
559                //printf("%d: temp_sts_data[%d]=%f\n", i, k, temp_sts_data[k]);     
560
561            }
562
563
564            // Update metadata (e.g. start time and end time)
565            N = number_of_time_steps;
566
567            if (isrc == 0) {
568                // Assign values for first source
569                sts_data[i][N] = (float)mytgs0[ista].geolat;
570                sts_data[i][N+1] = (float)mytgs0[ista].geolon;
571                sts_data[i][N+2] = (float)mytgs0[ista].z;
572                sts_data[i][N+3] = (float)fros_per_source[ista];
573                sts_data[i][N+4] = (float)lros_per_source[ista];
574            } else {
575                // Update first and last timesteps for subsequent sources
576                if (sts_data[i][N+3] > (float)fros_per_source[ista]) {         
577                    if (verbose) {
578                        printf("Adjusting start time for station %d and source %d",
579                            ista, isrc);
580                        printf(" from %f to %f\n", 
581                            sts_data[i][N+3], 
582                            (float) fros_per_source[ista]); 
583                    }
584                    sts_data[i][N+3] = (float) fros_per_source[ista];
585                }
586
587                if (sts_data[i][N+4] < (float) lros_per_source[ista]) {         
588                    if (verbose) {
589                        printf("Adjusting end time for station %d and source %d",
590                            ista, isrc);
591                        printf(" from %f to %f\n", 
592                            sts_data[i][N+4], 
593                            (float) lros_per_source[ista]); 
594                    }
595                    sts_data[i][N+4] = (float) lros_per_source[ista];
596                }               
597            }
598        }
599    }
600
601    //printf("sts_data[1,8]=%f\n", sts_data[1][8]);
602
603    free(muxData);
604    free(temp_sts_data);
605    free(fros);
606    free(lros);
607    free(mytgs0);
608
609    if (permutation_temp)
610    {
611        free(permutation_temp);
612    }
613
614    return sts_data;
615}
616
617/////////////////////////////////////////////////////////////////////////
618//Python gateways
619PyObject *read_mux2(PyObject *self, PyObject *args)
620{
621    /*Read in mux 2 file
622
623    Python call:
624    read_mux2(numSrc,filenames,weights,file_params,permutation,verbose)
625
626    NOTE:
627    A Python int is equivalent to a C long
628    (this becomes really important on 64 bit architectures)
629
630    A Python double corresponds to a C double
631    */
632
633    PyObject *filenames;
634    PyArrayObject *pyweights;
635    PyArrayObject *file_params;
636    PyArrayObject *permutation;  // Ordering of selected stations   
637    PyArrayObject *pydata;
638    PyObject *fname;
639
640    char **muxFileNameArray;
641    float **cdata;
642    float *weights;
643    int dimensions[2];
644    int numSrc;
645    int verbose;
646    int total_number_of_stations;
647    int number_of_selected_stations;   
648    int nt;
649    double dt;
650    int i;
651    int j;
652    int start_tstep;
653    int finish_tstep;
654    int it;
655    int time;
656    int num_ts;
657
658    // Convert Python arguments to C
659    if (!PyArg_ParseTuple(args, "iOOOOi",
660        &numSrc, &filenames, &pyweights, &file_params, 
661        &permutation, &verbose)) 
662    {
663        PyErr_SetString(PyExc_RuntimeError, 
664            "Input arguments to read_mux2 failed");
665        return NULL;
666    }
667
668    if(!PyList_Check(filenames)) 
669    {
670        PyErr_SetString(PyExc_TypeError, "get_first_elem expects a list");
671        return NULL;
672    }
673
674    if(PyList_Size(filenames) == 0)
675    {
676        PyErr_SetString(PyExc_ValueError, "empty lists not allowed");
677        return NULL;
678    }
679
680    if (pyweights->nd != 1 || pyweights->descr->type_num != PyArray_DOUBLE) 
681    {
682        PyErr_SetString(PyExc_ValueError,
683            "pyweights must be one-dimensional and of type double");
684        return NULL; 
685    }
686
687    if(PyList_Size(filenames) != pyweights->dimensions[0])
688    {
689        PyErr_SetString(PyExc_ValueError, 
690            "Must specify one weight for each filename");
691        return NULL;
692    }
693
694    muxFileNameArray = (char**)malloc(numSrc*sizeof(char*));
695    if (muxFileNameArray == NULL) 
696    {
697        PyErr_SetString(PyExc_ValueError, 
698            "ERROR: Memory for muxFileNameArray could not be allocated.");
699
700        return NULL;
701    }
702
703    for (i = 0; i < numSrc; i++)
704    {
705
706        fname = PyList_GetItem(filenames, i);
707        if (!fname) 
708        {
709            PyErr_SetString(PyExc_ValueError, "filename not a string");
710            free(muxFileNameArray);
711
712            return NULL;
713        }       
714
715        muxFileNameArray[i] = PyString_AsString(fname);
716        if (muxFileNameArray[i] == NULL) 
717        {
718            PyErr_SetString(PyExc_ValueError, 
719                "ERROR: Memory for muxFileNameArray could not be allocated.\n");
720            free(muxFileNameArray);
721
722            return NULL;
723        }
724    }
725
726    if (file_params->nd != 1 || file_params->descr->type_num != PyArray_DOUBLE) 
727    {
728        PyErr_SetString(PyExc_ValueError,
729            "file_params must be one-dimensional and of type double");
730        free(muxFileNameArray);
731
732        return NULL; 
733    }
734
735
736    // Create array for weights which are passed to read_mux2
737    weights = (float*) malloc(numSrc*sizeof(float));
738    if (weights == NULL) 
739    {
740        PyErr_SetString(PyExc_ValueError, 
741            "ERROR: Memory for weights could not be allocated.");
742        free(muxFileNameArray);
743        return NULL;
744    }
745
746
747    for (i = 0; i < numSrc; i++)
748    {
749        weights[i] = (float)(*(double*)(pyweights->data + i*pyweights->strides[0]));
750    }
751
752    // Desired number of stations
753    number_of_selected_stations = (int) permutation->dimensions[0];
754
755    // Read in mux2 data from file
756    cdata = _read_mux2(numSrc, 
757        muxFileNameArray, 
758        weights, 
759        (double*)file_params->data,
760        &number_of_selected_stations, 
761        (long*) permutation->data,
762        verbose);
763
764    if (!cdata) 
765    {
766        PyErr_SetString(PyExc_RuntimeError, "No STS_DATA returned");
767        return NULL;
768    }       
769
770    //Extracting data
771    total_number_of_stations = (int)*((double*)(file_params->data + 0*file_params->strides[0]));
772    dt = *(double*)(file_params->data + 1*file_params->strides[0]);
773    nt = (int)*(double*)(file_params->data + 2*file_params->strides[0]);
774
775
776    // Find min and max start times of all gauges
777    start_tstep = nt + 1;
778    finish_tstep = -1;
779    for (i = 0; i < number_of_selected_stations; i++)
780    {
781        //printf("cdata[%d] start = %f\n", i, (double) cdata[i][nt+3]);
782        // printf("cdata[%d] finish = %f\n", i, (double) cdata[i][nt+4]);   
783
784        if ((int)cdata[i][nt + 3] < start_tstep)
785        {
786            start_tstep = (int)cdata[i][nt + 3];
787        }
788        if ((int)cdata[i][nt + 4] > finish_tstep)
789        {
790            finish_tstep = (int)cdata[i][nt + 4]; 
791        }
792    }
793
794    if ((start_tstep > nt) | (finish_tstep < 0))
795    {
796        printf("ERROR: Gauge data has incorrect start and finish times:\n");
797        printf("   start_tstep = %d, max_number_of_steps = %d\n", 
798            start_tstep, nt);
799        printf("   finish_tstep = %d, min_number_of_steps = %d\n", 
800            finish_tstep, 0);   
801
802        PyErr_SetString(PyExc_ValueError, "Incorrect start and finish times"); 
803
804        free(weights);
805        free(muxFileNameArray);
806        for (i = 0; i < number_of_selected_stations; ++i)
807        {
808            free(cdata[i]);
809        }
810        free(cdata);
811
812        return NULL;
813    }
814
815    if (start_tstep >= finish_tstep)
816    {
817        PyErr_SetString(PyExc_ValueError,
818            "ERROR: Gauge data has non-postive_length");
819        free(weights);
820        free(muxFileNameArray);
821        for (i = 0; i < number_of_selected_stations; ++i)
822        {
823            free(cdata[i]);
824        }
825        free(cdata);
826
827        return NULL;
828    }
829
830    num_ts = finish_tstep - start_tstep + 1;
831    dimensions[0] = number_of_selected_stations;
832    dimensions[1] = num_ts + POFFSET;
833
834    pydata = (PyArrayObject*) anuga_FromDims(2, dimensions, PyArray_DOUBLE);
835    if(pydata == NULL)
836    {
837        PyErr_SetString(PyExc_RuntimeError, 
838            "ERROR: Memory for pydata array could not be allocated.");
839        free(weights);
840        free(muxFileNameArray);
841        for (i = 0; i < number_of_selected_stations; ++i)
842        {
843            free(cdata[i]);
844        }
845        free(cdata);
846
847        return NULL;
848    }
849
850
851    // Each gauge begins and ends recording at different times. When a gauge is
852    // not recording but at least one other gauge is.
853    // Pad the non-recording gauge array with zeros.
854    //printf("\nData put into the cdata array from C code\n");
855    for (i = 0; i < number_of_selected_stations; i++)
856    {
857        time = 0;
858        for (it = 0; it < finish_tstep; it++)
859        {
860            if ((it + 1 >= start_tstep) && (it + 1 <= finish_tstep))
861            {
862                if (it + 1 > (int)cdata[i][nt + 4])
863                {
864                    // This gauge has stopped recording but others are
865                    // still recording
866                    *(double*)(pydata->data + i*pydata->strides[0] 
867                    + time*pydata->strides[1]) = 
868                        0.0;
869                }
870                else
871                {
872                    //printf("cdata[%d][%d] = %f\n", i, it, cdata[i][it]);
873
874                    *(double*)(pydata->data + i*pydata->strides[0] 
875                    + time*pydata->strides[1]) = 
876                        cdata[i][it];
877                }
878                time++;
879            }
880        }
881        // Pass back lat,lon,elevation
882        for (j = 0; j < POFFSET; j++)
883        {
884            *(double*)(pydata->data + i*pydata->strides[0] 
885            + (num_ts + j)*pydata->strides[1]) = 
886                cdata[i][nt + j];
887        }
888    }
889
890    free(weights);
891
892    // Free filename array, but not independent Python strings
893    // FIXME(Ole): Do we need to update a reference counter in this case?
894    free(muxFileNameArray);
895
896    for (i = 0; i < number_of_selected_stations; ++i)
897    {
898        free(cdata[i]);
899    }
900    free(cdata);
901
902    return PyArray_Return(pydata);
903}
904
905//-------------------------------
906// Method table for python module
907//-------------------------------
908static struct PyMethodDef MethodTable[] = {
909    {"read_mux2", read_mux2, METH_VARARGS, "Print out"},
910    {NULL, NULL}
911};
912
913// Module initialisation
914void initurs_ext(void){
915    Py_InitModule("urs_ext", MethodTable);
916
917    import_array(); // Necessary for handling of NumPY structures
918}
Note: See TracBrowser for help on using the repository browser.