123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153 |
- /* v5d.c */
- /* Vis5D version 5.0 */
- /*
- Vis5D system for visualizing five dimensional gridded data sets
- Copyright (C) 1990 - 1997 Bill Hibbard, Johan Kellum, Brian Paul,
- Dave Santek, and Andre Battaiola.
- 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; either version 1, or (at your option)
- any later version.
- 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.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- /* this should be updated when the file version changes */
- #define FILE_VERSION "4.3"
- /*
- * New grid file format for VIS-5D:
- *
- * The header is a list of tagged items. Each item has 3 parts:
- * 1. A tag which is a 4-byte integer identifying the type of item.
- * 2. A 4-byte integer indicating how many bytes of data follow.
- * 3. The binary data.
- *
- * If we need to add new information to a file header we just create a
- * new tag and add the code to read/write the information.
- *
- * If we're reading a header and find an unknown tag, we can use the
- * length field to skip ahead to the next tag. Therefore, the file
- * format is forward (and backward) compatible.
- *
- * Grid data is stored as either:
- * 1-byte unsigned integers (255=missing)
- * 2-byte unsigned integers (65535=missing)
- * 4-byte IEEE floats ( >1.0e30 = missing)
- *
- * All numeric values are stored in big endian order. All floating point
- * values are in IEEE format.
- */
- /*
- * Updates:
- *
- * April 13, 1995, brianp
- * finished Cray support for 2-byte and 4-byte compress modes
- */
- #include <grass/config.h>
- #include <assert.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <grass/gis.h>
- #include "binio.h"
- #include "v5d.h"
- #include "vis5d.h"
- #ifndef SEEK_SET
- # define SEEK_SET 0
- #endif
- #ifndef SEEK_CUR
- # define SEEK_CUR 1
- #endif
- #ifndef SEEK_END
- # define SEEK_END 2
- #endif
- /*
- * Currently defined tags:
- * Note: the notation a[i] doesn't mean a is an array of i elements,
- * rather it just refers to the ith element of a[].
- *
- * Tags marked as PHASED OUT should be readable but are no longer written.
- * Old tag numbers can't be reused!
- *
- */
- /* TAG NAME VALUE DATA (comments) */
- /*----------------------------------------------------------------------*/
- #define TAG_ID 0x5635440a /* hex encoding of "V5D\n" */
- /* general stuff 1000+ */
- #define TAG_VERSION 1000 /* char*10 FileVersion */
- #define TAG_NUMTIMES 1001 /* int*4 NumTimes */
- #define TAG_NUMVARS 1002 /* int*4 NumVars */
- #define TAG_VARNAME 1003 /* int*4 var; char*10 VarName[var] */
- #define TAG_NR 1004 /* int*4 Nr */
- #define TAG_NC 1005 /* int*4 Nc */
- #define TAG_NL 1006 /* int*4 Nl (Nl for all vars) */
- #define TAG_NL_VAR 1007 /* int*4 var; int*4 Nl[var] */
- #define TAG_LOWLEV_VAR 1008 /* int*4 var; int*4 LowLev[var] */
- #define TAG_TIME 1010 /* int*4 t; int*4 TimeStamp[t] */
- #define TAG_DATE 1011 /* int*4 t; int*4 DateStamp[t] */
- #define TAG_MINVAL 1012 /* int*4 var; real*4 MinVal[var] */
- #define TAG_MAXVAL 1013 /* int*4 var; real*4 MaxVal[var] */
- #define TAG_COMPRESS 1014 /* int*4 CompressMode; (#bytes/grid) */
- #define TAG_UNITS 1015 /* int *4 var; char*20 Units[var] */
- /* vertical coordinate system 2000+ */
- #define TAG_VERTICAL_SYSTEM 2000 /* int*4 VerticalSystem */
- #define TAG_VERT_ARGS 2100 /* int*4 n; real*4 VertArgs[0..n-1] */
- #define TAG_BOTTOMBOUND 2001 /* real*4 BottomBound (PHASED OUT) */
- #define TAG_LEVINC 2002 /* real*4 LevInc (PHASED OUT) */
- #define TAG_HEIGHT 2003 /* int*4 l; real*4 Height[l] (PHASED OUT) */
- /* projection 3000+ */
- #define TAG_PROJECTION 3000 /* int*4 projection: */
- /* 0 = generic linear */
- /* 1 = cylindrical equidistant */
- /* 2 = Lambert conformal/Polar Stereo */
- /* 3 = rotated equidistant */
- #define TAG_PROJ_ARGS 3100 /* int *4 n; real*4 ProjArgs[0..n-1] */
- #define TAG_NORTHBOUND 3001 /* real*4 NorthBound (PHASED OUT) */
- #define TAG_WESTBOUND 3002 /* real*4 WestBound (PHASED OUT) */
- #define TAG_ROWINC 3003 /* real*4 RowInc (PHASED OUT) */
- #define TAG_COLINC 3004 /* real*4 ColInc (PHASED OUT) */
- #define TAG_LAT1 3005 /* real*4 Lat1 (PHASED OUT) */
- #define TAG_LAT2 3006 /* real*4 Lat2 (PHASED OUT) */
- #define TAG_POLE_ROW 3007 /* real*4 PoleRow (PHASED OUT) */
- #define TAG_POLE_COL 3008 /* real*4 PoleCol (PHASED OUT) */
- #define TAG_CENTLON 3009 /* real*4 CentralLon (PHASED OUT) */
- #define TAG_CENTLAT 3010 /* real*4 CentralLat (PHASED OUT) */
- #define TAG_CENTROW 3011 /* real*4 CentralRow (PHASED OUT) */
- #define TAG_CENTCOL 3012 /* real*4 CentralCol (PHASED OUT) */
- #define TAG_ROTATION 3013 /* real*4 Rotation (PHASED OUT) */
- #define TAG_END 9999
- /**********************************************************************/
- /***** Miscellaneous Functions *****/
- /**********************************************************************/
- float pressure_to_height(float pressure)
- {
- return (float)DEFAULT_LOG_EXP *log((double)pressure / DEFAULT_LOG_SCALE);
- }
- float height_to_pressure(float height)
- {
- return (float)DEFAULT_LOG_SCALE *exp((double)height / DEFAULT_LOG_EXP);
- }
- /*
- * Return current file position.
- * Input: f - file descriptor
- */
- static off_t ltell(int f)
- {
- return lseek(f, 0, SEEK_CUR);
- }
- /*
- * Copy up to maxlen characters from src to dst stopping upon whitespace
- * in src. Terminate dst with null character.
- * Return: length of dst.
- */
- static int copy_string2(char *dst, const char *src, int maxlen)
- {
- int i;
- for (i = 0; i < maxlen; i++)
- dst[i] = src[i];
- for (i = maxlen - 1; i >= 0; i--) {
- if (dst[i] == ' ' || i == maxlen - 1)
- dst[i] = 0;
- else
- break;
- }
- return strlen(dst);
- }
- /*
- * Copy up to maxlen characters from src to dst stopping upon whitespace
- * in src. Terminate dst with null character.
- * Return: length of dst.
- */
- static int copy_string(char *dst, const char *src, int maxlen)
- {
- int i;
- for (i = 0; i < maxlen; i++) {
- if (src[i] == ' ' || i == maxlen - 1) {
- dst[i] = 0;
- break;
- }
- else {
- dst[i] = src[i];
- }
- }
- return i;
- }
- /*
- * Convert a date from YYDDD format to days since Jan 1, 1900.
- */
- int v5dYYDDDtoDays(int yyddd)
- {
- int iy, id, idays;
- iy = yyddd / 1000;
- id = yyddd - 1000 * iy;
- if (iy < 50)
- iy += 100; /* WLH 31 July 96 << 31 Dec 99 */
- idays = 365 * iy + (iy - 1) / 4 + id;
- return idays;
- }
- /*
- * Convert a time from HHMMSS format to seconds since midnight.
- */
- int v5dHHMMSStoSeconds(int hhmmss)
- {
- int h, m, s;
- h = hhmmss / 10000;
- m = (hhmmss / 100) % 100;
- s = hhmmss % 100;
- return s + m * 60 + h * 60 * 60;
- }
- /*
- * Convert a day since Jan 1, 1900 to YYDDD format.
- */
- int v5dDaysToYYDDD(int days)
- {
- int iy, id, iyyddd;
- iy = (4 * days) / 1461;
- id = days - (365 * iy + (iy - 1) / 4);
- if (iy > 99)
- iy = iy - 100; /* WLH 31 July 96 << 31 Dec 99 */
- /* iy = iy + 1900; is the right way to fix this, but requires
- changing all places where dates are printed - procrastinate */
- iyyddd = iy * 1000 + id;
- return iyyddd;
- }
- /*
- * Convert a time in seconds since midnight to HHMMSS format.
- */
- int v5dSecondsToHHMMSS(int seconds)
- {
- int hh, mm, ss;
- hh = seconds / (60 * 60);
- mm = (seconds / 60) % 60;
- ss = seconds % 60;
- return hh * 10000 + mm * 100 + ss;
- }
- void v5dPrintStruct(const v5dstruct * v)
- {
- static char day[7][10] = { "Sunday", "Monday", "Tuesday", "Wednesday",
- "Thursday", "Friday", "Saturday"
- };
- int time, var, i;
- int maxnl;
- maxnl = 0;
- for (var = 0; var < v->NumVars; var++) {
- if (v->Nl[var] + v->LowLev[var] > maxnl) {
- maxnl = v->Nl[var] + v->LowLev[var];
- }
- }
- if (v->FileFormat == 0) {
- if (v->FileVersion[0] == 0) {
- printf("File format: v5d version: (4.0 or 4.1)\n");
- }
- else {
- printf("File format: v5d version: %s\n", v->FileVersion);
- }
- }
- else {
- printf("File format: comp5d (VIS-5D 3.3 or older)\n");
- }
- if (v->CompressMode == 1) {
- printf("Compression: 1 byte per gridpoint.\n");
- }
- else {
- printf("Compression: %d bytes per gridpoint.\n", v->CompressMode);
- }
- printf("header size=%d\n", (int)v->FirstGridPos);
- printf("sizeof(v5dstruct)=%d\n", (int)sizeof(v5dstruct));
- printf("\n");
- printf("NumVars = %d\n", v->NumVars);
- printf
- ("Var Name Units Rows Cols Levels LowLev MinVal MaxVal\n");
- for (var = 0; var < v->NumVars; var++) {
- printf("%3d %-10s %-10s %3d %3d %3d %3d",
- var + 1, v->VarName[var], v->Units[var],
- v->Nr, v->Nc, v->Nl[var], v->LowLev[var]);
- if (v->MinVal[var] > v->MaxVal[var]) {
- printf(" MISSING MISSING\n");
- }
- else {
- printf(" %-12g %-12g\n", v->MinVal[var], v->MaxVal[var]);
- }
- }
- printf("\n");
- printf("NumTimes = %d\n", v->NumTimes);
- printf("Step Date(YYDDD) Time(HH:MM:SS) Day\n");
- for (time = 0; time < v->NumTimes; time++) {
- int i = v->TimeStamp[time];
- printf("%3d %05d %5d:%02d:%02d %s\n",
- time + 1,
- v->DateStamp[time],
- i / 10000, (i / 100) % 100, i % 100,
- day[v5dYYDDDtoDays(v->DateStamp[time]) % 7]);
- }
- printf("\n");
- switch (v->VerticalSystem) {
- case 0:
- printf("Generic linear vertical coordinate system:\n");
- printf("\tBottom Bound: %f\n", v->VertArgs[0]);
- printf("\tIncrement between levels: %f\n", v->VertArgs[1]);
- break;
- case 1:
- printf("Equally spaced levels in km:\n");
- printf("\tBottom Bound: %f\n", v->VertArgs[0]);
- printf("\tIncrement: %f\n", v->VertArgs[1]);
- break;
- case 2:
- printf("Unequally spaced levels in km:\n");
- printf("Level\tHeight(km)\n");
- for (i = 0; i < maxnl; i++) {
- printf("%3d %10.3f\n", i + 1, v->VertArgs[i]);
- }
- break;
- case 3:
- printf("Unequally spaced levels in mb:\n");
- printf("Level\tPressure(mb)\n");
- for (i = 0; i < maxnl; i++) {
- printf("%3d %10.3f\n", i + 1,
- height_to_pressure(v->VertArgs[i]));
- }
- break;
- default:
- printf("Bad VerticalSystem value: %d\n", v->VerticalSystem);
- }
- printf("\n");
- switch (v->Projection) {
- case 0:
- printf("Generic linear projection:\n");
- printf("\tNorth Boundary: %f\n", v->ProjArgs[0]);
- printf("\tWest Boundary: %f\n", v->ProjArgs[1]);
- printf("\tRow Increment: %f\n", v->ProjArgs[2]);
- printf("\tColumn Increment: %f\n", v->ProjArgs[3]);
- break;
- case 1:
- printf("Cylindrical Equidistant projection:\n");
- printf("\tNorth Boundary: %f degrees\n", v->ProjArgs[0]);
- printf("\tWest Boundary: %f degrees\n", v->ProjArgs[1]);
- printf("\tRow Increment: %f degrees\n", v->ProjArgs[2]);
- printf("\tColumn Increment: %f degrees\n", v->ProjArgs[3]);
- /*
- printf("\tSouth Boundary: %f degrees\n",
- v->NorthBound - v->RowInc * (v->Nr-1) );
- printf("\tEast Boundary: %f degrees\n",
- v->WestBound - v->ColInc * (v->Nc-1) );
- */
- break;
- case 2:
- printf("Lambert Conformal projection:\n");
- printf("\tStandard Latitude 1: %f\n", v->ProjArgs[0]);
- printf("\tStandard Latitude 2: %f\n", v->ProjArgs[1]);
- printf("\tNorth/South Pole Row: %f\n", v->ProjArgs[2]);
- printf("\tNorth/South Pole Column: %f\n", v->ProjArgs[3]);
- printf("\tCentral Longitude: %f\n", v->ProjArgs[4]);
- printf("\tColumn Increment: %f km\n", v->ProjArgs[5]);
- break;
- case 3:
- printf("Stereographic:\n");
- printf("\tCenter Latitude: %f\n", v->ProjArgs[0]);
- printf("\tCenter Longitude: %f\n", v->ProjArgs[1]);
- printf("\tCenter Row: %f\n", v->ProjArgs[2]);
- printf("\tCenter Column: %f\n", v->ProjArgs[3]);
- printf("\tColumn Spacing: %f\n", v->ProjArgs[4]);
- break;
- case 4:
- /* WLH 4-21-95 */
- printf("Rotated equidistant projection:\n");
- printf("\tLatitude of grid(0,0): %f\n", v->ProjArgs[0]);
- printf("\tLongitude of grid(0,0): %f\n", v->ProjArgs[1]);
- printf("\tRow Increment: %f degress\n", v->ProjArgs[2]);
- printf("\tColumn Increment: %f degrees\n", v->ProjArgs[3]);
- printf("\tCenter Latitude: %f\n", v->ProjArgs[4]);
- printf("\tCenter Longitude: %f\n", v->ProjArgs[5]);
- printf("\tRotation: %f degrees\n", v->ProjArgs[6]);
- break;
- default:
- printf("Bad projection number: %d\n", v->Projection);
- }
- }
- /*
- * Compute the location of a compressed grid within a file.
- * Input: v - pointer to v5dstruct describing the file header.
- * time, var - which timestep and variable.
- * Return: file offset in bytes
- */
- static off_t grid_position(const v5dstruct * v, int time, int var)
- {
- int i;
- off_t pos;
- assert(time >= 0);
- assert(var >= 0);
- assert(time < v->NumTimes);
- assert(var < v->NumVars);
- pos = v->FirstGridPos + time * v->SumGridSizes;
- for (i = 0; i < var; i++) {
- pos += v->GridSize[i];
- }
- return pos;
- }
- /*
- * Compute the ga and gb (de)compression values for a grid.
- * Input: nr, nc, nl - size of grid
- * data - the grid data
- * ga, gb - arrays to store results.
- * minval, maxval - pointer to floats to return min, max values
- * compressmode - 1, 2 or 4 bytes per grid point
- * Output: ga, gb - the (de)compression values
- * minval, maxval - the min and max grid values
- * Side effect: the MinVal[var] and MaxVal[var] fields in g may be
- * updated with new values.
- */
- static void compute_ga_gb(int nr, int nc, int nl,
- const float data[], int compressmode,
- float ga[], float gb[],
- float *minval, float *maxval)
- {
- #ifdef SIMPLE_COMPRESSION
- /*
- * Compute ga, gb values for whole grid.
- */
- int i, lev, allmissing, num;
- float min, max, a, b;
- min = 1.0e30;
- max = -1.0e30;
- num = nr * nc * nl;
- allmissing = 1;
- for (i = 0; i < num; i++) {
- if (!IS_MISSING(data[i])) {
- if (data[i] < min)
- min = data[i];
- if (data[i] > max)
- max = data[i];
- allmissing = 0;
- }
- }
- if (allmissing) {
- a = 1.0;
- b = 0.0;
- }
- else {
- a = (max - min) / 254.0;
- b = min;
- }
- /* return results */
- for (i = 0; i < nl; i++) {
- ga[i] = a;
- gb[i] = b;
- }
- *minval = min;
- *maxval = max;
- #else
- /*
- * Compress grid on level-by-level basis.
- */
- # define SMALLVALUE -1.0e30
- # define BIGVALUE 1.0e30
- # define ABS(x) ( ((x) < 0.0) ? -(x) : (x) )
- float gridmin, gridmax;
- float levmin[MAXLEVELS], levmax[MAXLEVELS];
- float d[MAXLEVELS], dmax;
- float ival, mval;
- int j, k, lev, nrnc;
- nrnc = nr * nc;
- /* find min and max for each layer and the whole grid */
- gridmin = BIGVALUE;
- gridmax = SMALLVALUE;
- j = 0;
- for (lev = 0; lev < nl; lev++) {
- float min, max;
- min = BIGVALUE;
- max = SMALLVALUE;
- for (k = 0; k < nrnc; k++) {
- if (!IS_MISSING(data[j]) && data[j] < min)
- min = data[j];
- if (!IS_MISSING(data[j]) && data[j] > max)
- max = data[j];
- j++;
- }
- if (min < gridmin)
- gridmin = min;
- if (max > gridmax)
- gridmax = max;
- levmin[lev] = min;
- levmax[lev] = max;
- }
- /* WLH 2-2-95 */
- #ifdef KLUDGE
- /* if the grid minimum is within delt of 0.0, fudge all values */
- /* within delt of 0.0 to delt, and recalculate mins and maxes */
- {
- float delt;
- int nrncnl = nrnc * nl;
- delt = (gridmax - gridmin) / 100000.0;
- if (ABS(gridmin) < delt && gridmin != 0.0 && compressmode != 4) {
- float min, max;
- for (j = 0; j < nrncnl; j++) {
- if (!IS_MISSING(data[j]) && data[j] < delt)
- data[j] = delt;
- }
- /* re-calculate min and max for each layer and the whole grid */
- gridmin = delt;
- for (lev = 0; lev < nl; lev++) {
- if (ABS(levmin[lev]) < delt)
- levmin[lev] = delt;
- if (ABS(levmax[lev]) < delt)
- levmax[lev] = delt;
- }
- }
- }
- #endif
- /* find d[lev] and dmax = MAX( d[0], d[1], ... d[nl-1] ) */
- dmax = 0.0;
- for (lev = 0; lev < nl; lev++) {
- if (levmin[lev] >= BIGVALUE && levmax[lev] <= SMALLVALUE) {
- /* all values in the layer are MISSING */
- d[lev] = 0.0;
- }
- else {
- d[lev] = levmax[lev] - levmin[lev];
- }
- if (d[lev] > dmax)
- dmax = d[lev];
- }
- /*** Compute ga (scale) and gb (bias) for each grid level */
- if (dmax == 0.0) {
- /*** Special cases ***/
- if (gridmin == gridmax) {
- /*** whole grid is of same value ***/
- for (lev = 0; lev < nl; lev++) {
- ga[lev] = gridmin;
- gb[lev] = 0.0;
- }
- }
- else {
- /*** every layer is of a single value ***/
- for (lev = 0; lev < nl; lev++) {
- ga[lev] = levmin[lev];
- gb[lev] = 0.0;
- }
- }
- }
- else {
- /*** Normal cases ***/
- if (compressmode == 1) {
- #define ORIGINAL
- #ifdef ORIGINAL
- ival = dmax / 254.0;
- mval = gridmin;
- for (lev = 0; lev < nl; lev++) {
- ga[lev] = ival;
- gb[lev] = mval + ival * (int)((levmin[lev] - mval) / ival);
- }
- #else
- for (lev = 0; lev < nl; lev++) {
- if (d[lev] == 0.0) {
- ival = 1.0;
- }
- else {
- ival = d[lev] / 254.0;
- }
- ga[lev] = ival;
- gb[lev] = levmin[lev];
- }
- #endif
- }
- else if (compressmode == 2) {
- ival = dmax / 65534.0;
- mval = gridmin;
- for (lev = 0; lev < nl; lev++) {
- ga[lev] = ival;
- gb[lev] = mval + ival * (int)((levmin[lev] - mval) / ival);
- }
- }
- else {
- assert(compressmode == 4);
- for (lev = 0; lev < nl; lev++) {
- ga[lev] = 1.0;
- gb[lev] = 0.0;
- }
- }
- }
- /* update min, max values */
- *minval = gridmin;
- *maxval = gridmax;
- #endif
- }
- /*
- * Compress a 3-D grid from floats to 1-byte unsigned integers.
- * Input: nr, nc, nl - size of grid
- * compressmode - 1, 2 or 4 bytes per grid point
- * data - array of [nr*nc*nl] floats
- * compdata - pointer to array of [nr*nc*nl*compressmode] bytes
- * to put results into.
- * ga, gb - pointer to arrays to put ga and gb decompression values
- * minval, maxval - pointers to float to return min & max values
- * Output: compdata - the compressed grid data
- * ga, gb - the decompression values
- * minval, maxval - the min and max grid values
- */
- void v5dCompressGrid(int nr, int nc, int nl, int compressmode,
- const float data[],
- void *compdata, float ga[], float gb[],
- float *minval, float *maxval)
- {
- int nrnc = nr * nc;
- int nrncnl = nr * nc * nl;
- V5Dubyte *compdata1 = (V5Dubyte *) compdata;
- V5Dushort *compdata2 = (V5Dushort *) compdata;
- /* compute ga, gb values */
- compute_ga_gb(nr, nc, nl, data, compressmode, ga, gb, minval, maxval);
- /* compress the data */
- if (compressmode == 1) {
- int i, lev, p;
- p = 0;
- for (lev = 0; lev < nl; lev++) {
- float one_over_a, b;
- b = gb[lev] - 0.0001; /* subtract an epsilon so the int((d-b)/a) */
- /* expr below doesn't get mis-truncated. */
- if (ga[lev] == 0.0) {
- one_over_a = 1.0;
- }
- else {
- one_over_a = 1.0 / ga[lev];
- }
- for (i = 0; i < nrnc; i++, p++) {
- if (IS_MISSING(data[p])) {
- compdata1[p] = 255;
- }
- else {
- compdata1[p] =
- (V5Dubyte) (int)((data[p] - b) * one_over_a);
- if (compdata1[p] >= 255) {
- compdata1[p] = (V5Dubyte) (int)(255.0 - .0001);
- }
- }
- }
- }
- }
- else if (compressmode == 2) {
- int i, lev, p;
- p = 0;
- for (lev = 0; lev < nl; lev++) {
- float one_over_a, b;
- b = gb[lev] - 0.0001;
- if (ga[lev] == 0.0) {
- one_over_a = 1.0;
- }
- else {
- one_over_a = 1.0 / ga[lev];
- }
- #ifdef _CRAY
- /* this is tricky because sizeof(V5Dushort)==8, not 2 */
- for (i = 0; i < nrnc; i++, p++) {
- V5Dushort compvalue;
- if (IS_MISSING(data[p])) {
- compvalue = 65535;
- }
- else {
- compvalue = (V5Dushort) (int)((data[p] - b) * one_over_a);
- }
- compdata1[p * 2 + 0] = compvalue >> 8; /* upper byte */
- compdata1[p * 2 + 1] = compvalue & 0xffu; /* lower byte */
- }
- #else
- for (i = 0; i < nrnc; i++, p++) {
- if (IS_MISSING(data[p])) {
- compdata2[p] = 65535;
- }
- else {
- compdata2[p] =
- (V5Dushort) (int)((data[p] - b) * one_over_a);
- }
- }
- /* TODO: byte-swapping on little endian??? */
- #endif
- }
- }
- else {
- /* compressmode==4 */
- #ifdef _CRAY
- cray_to_ieee_array(compdata, data, nrncnl);
- #else
- /* other machines: just copy 4-byte IEEE floats */
- assert(sizeof(float) == 4);
- memcpy(compdata, data, nrncnl * 4);
- /* TODO: byte-swapping on little endian??? */
- #endif
- }
- }
- /*
- * Decompress a 3-D grid from 1-byte integers to 4-byte floats.
- * Input: nr, nc, nl - size of grid
- * compdata - array of [nr*nr*nl*compressmode] bytes
- * ga, gb - arrays of decompression factors
- * compressmode - 1, 2 or 4 bytes per grid point
- * data - address to put decompressed values
- * Output: data - uncompressed floating point data values
- */
- void v5dDecompressGrid(int nr, int nc, int nl, int compressmode,
- void *compdata, float ga[], float gb[], float data[])
- {
- int nrnc = nr * nc;
- int nrncnl = nr * nc * nl;
- V5Dubyte *compdata1 = (V5Dubyte *) compdata;
- V5Dushort *compdata2 = (V5Dushort *) compdata;
- if (compressmode == 1) {
- int p, i, lev;
- p = 0;
- for (lev = 0; lev < nl; lev++) {
- float a = ga[lev];
- float b = gb[lev];
- /* WLH 2-2-95 */
- float d, aa;
- int id;
- if (a > 0.0000000001) {
- d = b / a;
- id = floor(d);
- d = d - id;
- aa = a * 0.000001;
- }
- else {
- id = 1;
- }
- if (-254 <= id && id <= 0 && d < aa) {
- for (i = 0; i < nrnc; i++, p++) {
- if (compdata1[p] == 255) {
- data[p] = MISSING;
- }
- else {
- data[p] = (float)(int)compdata1[p] * a + b;
- if (fabs(data[p]) < aa)
- data[p] = aa;
- }
- }
- }
- else {
- for (i = 0; i < nrnc; i++, p++) {
- if (compdata1[p] == 255) {
- data[p] = MISSING;
- }
- else {
- data[p] = (float)(int)compdata1[p] * a + b;
- }
- }
- }
- /* end of WLH 2-2-95 */
- }
- }
- else if (compressmode == 2) {
- int p, i, lev;
- p = 0;
- for (lev = 0; lev < nl; lev++) {
- float a = ga[lev];
- float b = gb[lev];
- #ifdef _CRAY
- /* this is tricky because sizeof(V5Dushort)==8, not 2 */
- for (i = 0; i < nrnc; i++, p++) {
- int compvalue;
- compvalue = (compdata1[p * 2] << 8) | compdata1[p * 2 + 1];
- if (compvalue == 65535) {
- data[p] = MISSING;
- }
- else {
- data[p] = (float)compvalue *a + b;
- }
- }
- #else
- /* sizeof(V5Dushort)==2! */
- for (i = 0; i < nrnc; i++, p++) {
- if (compdata2[p] == 65535) {
- data[p] = MISSING;
- }
- else {
- data[p] = (float)(int)compdata2[p] * a + b;
- }
- }
- #endif
- }
- }
- else {
- /* compressmode==4 */
- #ifdef _CRAY
- ieee_to_cray_array(data, compdata, nrncnl);
- #else
- /* other machines: just copy 4-byte IEEE floats */
- assert(sizeof(float) == 4);
- memcpy(data, compdata, nrncnl * 4);
- #endif
- }
- }
- /*
- * Return the size (in bytes) of the 3-D grid specified by time and var.
- * Input: v - pointer to v5dstruct describing the file
- * time, var - which timestep and variable
- * Return: number of data points.
- */
- int v5dSizeofGrid(const v5dstruct * v, int time, int var)
- {
- return v->Nr * v->Nc * v->Nl[var] * v->CompressMode;
- }
- /*
- * Initialize a v5dstructure to reasonable initial values.
- * Input: v - pointer to v5dstruct.
- */
- void v5dInitStruct(v5dstruct * v)
- {
- int i;
- /* set everything to zero */
- memset(v, 0, sizeof(v5dstruct));
- /* special cases */
- v->Projection = -1;
- v->VerticalSystem = -1;
- for (i = 0; i < MAXVARS; i++) {
- v->MinVal[i] = MISSING;
- v->MaxVal[i] = -MISSING;
- v->LowLev[i] = 0;
- }
- /* set file version */
- strcpy(v->FileVersion, FILE_VERSION);
- v->CompressMode = 1;
- v->FileDesc = -1;
- }
- /*
- * Return a pointer to a new, initialized v5dstruct.
- */
- v5dstruct *v5dNewStruct(void)
- {
- v5dstruct *v;
- v = (v5dstruct *) G_malloc(sizeof(v5dstruct));
- if (v) {
- v5dInitStruct(v);
- }
- return v;
- }
- /*
- * Free an initialized v5dstruct. (Todd Plessel)
- */
- void v5dFreeStruct(v5dstruct * v)
- {
- /*assert( v5dVerifyStruct( v ) ); */
- G_free(v);
- v = 0;
- }
- /*
- * Do some checking that the information in a v5dstruct is valid.
- * Input: v - pointer to v5dstruct
- * Return: 1 = g is ok, 0 = g is invalid
- */
- int v5dVerifyStruct(const v5dstruct * v)
- {
- int var, i, invalid, maxnl;
- invalid = 0;
- if (!v)
- return 0;
- /* Number of variables */
- if (v->NumVars < 0) {
- printf("Invalid number of variables: %d\n", v->NumVars);
- invalid = 1;
- }
- else if (v->NumVars > MAXVARS) {
- printf("Too many variables: %d (Maximum is %d)\n",
- v->NumVars, MAXVARS);
- invalid = 1;
- }
- /* Variable Names */
- for (i = 0; i < v->NumVars; i++) {
- if (v->VarName[i][0] == 0) {
- printf("Missing variable name: VarName[%d]=\"\"\n", i);
- invalid = 1;
- }
- }
- /* Number of timesteps */
- if (v->NumTimes < 0) {
- printf("Invalid number of timesteps: %d\n", v->NumTimes);
- invalid = 1;
- }
- else if (v->NumTimes > MAXTIMES) {
- printf("Too many timesteps: %d (Maximum is %d)\n",
- v->NumTimes, MAXTIMES);
- invalid = 1;
- }
- /* Make sure timestamps are increasing */
- for (i = 1; i < v->NumTimes; i++) {
- int date0 = v5dYYDDDtoDays(v->DateStamp[i - 1]);
- int date1 = v5dYYDDDtoDays(v->DateStamp[i]);
- int time0 = v5dHHMMSStoSeconds(v->TimeStamp[i - 1]);
- int time1 = v5dHHMMSStoSeconds(v->TimeStamp[i]);
- if (time1 <= time0 && date1 <= date0) {
- printf("Timestamp for step %d must be later than step %d\n", i,
- i - 1);
- invalid = 1;
- }
- }
- /* Rows */
- if (v->Nr < 2) {
- printf("Too few rows: %d (2 is minimum)\n", v->Nr);
- invalid = 1;
- }
- else if (v->Nr > MAXROWS) {
- printf("Too many rows: %d (%d is maximum)\n", v->Nr, MAXROWS);
- invalid = 1;
- }
- /* Columns */
- if (v->Nc < 2) {
- printf("Too few columns: %d (2 is minimum)\n", v->Nc);
- invalid = 1;
- }
- else if (v->Nc > MAXCOLUMNS) {
- printf("Too many columns: %d (%d is maximum)\n", v->Nc, MAXCOLUMNS);
- invalid = 1;
- }
- /* Levels */
- maxnl = 0;
- for (var = 0; var < v->NumVars; var++) {
- if (v->LowLev[var] < 0) {
- printf("Low level cannot be negative for var %s: %d\n",
- v->VarName[var], v->LowLev[var]);
- invalid = 1;
- }
- if (v->Nl[var] < 1) {
- printf("Too few levels for var %s: %d (1 is minimum)\n",
- v->VarName[var], v->Nl[var]);
- invalid = 1;
- }
- if (v->Nl[var] + v->LowLev[var] > MAXLEVELS) {
- printf("Too many levels for var %s: %d (%d is maximum)\n",
- v->VarName[var], v->Nl[var] + v->LowLev[var], MAXLEVELS);
- invalid = 1;
- }
- if (v->Nl[var] + v->LowLev[var] > maxnl) {
- maxnl = v->Nl[var] + v->LowLev[var];
- }
- }
- if (v->CompressMode != 1 && v->CompressMode != 2 && v->CompressMode != 4) {
- printf("Bad CompressMode: %d (must be 1, 2 or 4)\n", v->CompressMode);
- invalid = 1;
- }
- switch (v->VerticalSystem) {
- case 0:
- case 1:
- if (v->VertArgs[1] == 0.0) {
- printf("Vertical level increment is zero, must be non-zero\n");
- invalid = 1;
- }
- break;
- case 2:
- /* Check that Height values increase upward */
- for (i = 1; i < maxnl; i++) {
- if (v->VertArgs[i] <= v->VertArgs[i - 1]) {
- printf
- ("Height[%d]=%f <= Height[%d]=%f, level heights must increase\n",
- i, v->VertArgs[i], i - 1, v->VertArgs[i - 1]);
- invalid = 1;
- break;
- }
- }
- break;
- case 3:
- /* Check that Pressure values decrease upward */
- for (i = 1; i < maxnl; i++) {
- if (v->VertArgs[i] <= v->VertArgs[i - 1]) {
- printf
- ("Pressure[%d]=%f >= Pressure[%d]=%f, level pressures must decrease\n",
- i, height_to_pressure(v->VertArgs[i]), i - 1,
- height_to_pressure(v->VertArgs[i - 1]));
- invalid = 1;
- break;
- }
- }
- break;
- default:
- printf("VerticalSystem = %d, must be in 0..3\n", v->VerticalSystem);
- invalid = 1;
- }
- switch (v->Projection) {
- case 0: /* Generic */
- if (v->ProjArgs[2] == 0.0) {
- printf("Row Increment (ProjArgs[2]) can't be zero\n");
- invalid = 1;
- }
- if (v->ProjArgs[3] == 0.0) {
- printf("Column increment (ProjArgs[3]) can't be zero\n");
- invalid = 1;
- }
- break;
- case 1: /* Cylindrical equidistant */
- if (v->ProjArgs[2] < 0.0) {
- printf("Row Increment (ProjArgs[2]) = %g (must be >=0.0)\n",
- v->ProjArgs[2]);
- invalid = 1;
- }
- if (v->ProjArgs[3] <= 0.0) {
- printf("Column Increment (ProjArgs[3]) = %g (must be >=0.0)\n",
- v->ProjArgs[3]);
- invalid = 1;
- }
- break;
- case 2: /* Lambert Conformal */
- if (v->ProjArgs[0] < -90.0 || v->ProjArgs[0] > 90.0) {
- printf("Lat1 (ProjArgs[0]) out of range: %g\n", v->ProjArgs[0]);
- invalid = 1;
- }
- if (v->ProjArgs[1] < -90.0 || v->ProjArgs[1] > 90.0) {
- printf("Lat2 (ProjArgs[1] out of range: %g\n", v->ProjArgs[1]);
- invalid = 1;
- }
- if (v->ProjArgs[5] <= 0.0) {
- printf("ColInc (ProjArgs[5]) = %g (must be >=0.0)\n",
- v->ProjArgs[5]);
- invalid = 1;
- }
- break;
- case 3: /* Stereographic */
- if (v->ProjArgs[0] < -90.0 || v->ProjArgs[0] > 90.0) {
- printf("Central Latitude (ProjArgs[0]) out of range: ");
- printf("%g (must be in +/-90)\n", v->ProjArgs[0]);
- invalid = 1;
- }
- if (v->ProjArgs[1] < -180.0 || v->ProjArgs[1] > 180.0) {
- printf("Central Longitude (ProjArgs[1]) out of range: ");
- printf("%g (must be in +/-180)\n", v->ProjArgs[1]);
- invalid = 1;
- }
- if (v->ProjArgs[4] < 0) {
- printf("Column spacing (ProjArgs[4]) = %g (must be positive)\n",
- v->ProjArgs[4]);
- invalid = 1;
- }
- break;
- case 4: /* Rotated */
- /* WLH 4-21-95 */
- if (v->ProjArgs[2] <= 0.0) {
- printf("Row Increment (ProjArgs[2]) = %g (must be >=0.0)\n",
- v->ProjArgs[2]);
- invalid = 1;
- }
- if (v->ProjArgs[3] <= 0.0) {
- printf("Column Increment = (ProjArgs[3]) %g (must be >=0.0)\n",
- v->ProjArgs[3]);
- invalid = 1;
- }
- if (v->ProjArgs[4] < -90.0 || v->ProjArgs[4] > 90.0) {
- printf("Central Latitude (ProjArgs[4]) out of range: ");
- printf("%g (must be in +/-90)\n", v->ProjArgs[4]);
- invalid = 1;
- }
- if (v->ProjArgs[5] < -180.0 || v->ProjArgs[5] > 180.0) {
- printf("Central Longitude (ProjArgs[5]) out of range: ");
- printf("%g (must be in +/-180)\n", v->ProjArgs[5]);
- invalid = 1;
- }
- if (v->ProjArgs[6] < -180.0 || v->ProjArgs[6] > 180.0) {
- printf("Central Longitude (ProjArgs[6]) out of range: ");
- printf("%g (must be in +/-180)\n", v->ProjArgs[6]);
- invalid = 1;
- }
- break;
- default:
- printf("Projection = %d, must be in 0..4\n", v->Projection);
- invalid = 1;
- }
- return !invalid;
- }
- /*
- * Get the McIDAS file number and grid number associated with the grid
- * identified by time and var.
- * Input: v - v5d grid struct
- * time, var - timestep and variable of grid
- * Output: mcfile, mcgrid - McIDAS grid file number and grid number
- */
- int v5dGetMcIDASgrid(v5dstruct * v, int time, int var,
- int *mcfile, int *mcgrid)
- {
- if (time < 0 || time >= v->NumTimes) {
- printf("Bad time argument to v5dGetMcIDASgrid: %d\n", time);
- return 0;
- }
- if (var < 0 || var >= v->NumVars) {
- printf("Bad var argument to v5dGetMcIDASgrid: %d\n", var);
- return 0;
- }
- *mcfile = (int)v->McFile[time][var];
- *mcgrid = (int)v->McGrid[time][var];
- return 1;
- }
- /*
- * Set the McIDAS file number and grid number associated with the grid
- * identified by time and var.
- * Input: v - v5d grid struct
- * time, var - timestep and variable of grid
- * mcfile, mcgrid - McIDAS grid file number and grid number
- * Return: 1 = ok, 0 = error (bad time or var)
- */
- int v5dSetMcIDASgrid(v5dstruct * v, int time, int var, int mcfile, int mcgrid)
- {
- if (time < 0 || time >= v->NumTimes) {
- printf("Bad time argument to v5dSetMcIDASgrid: %d\n", time);
- return 0;
- }
- if (var < 0 || var >= v->NumVars) {
- printf("Bad var argument to v5dSetMcIDASgrid: %d\n", var);
- return 0;
- }
- v->McFile[time][var] = (short)mcfile;
- v->McGrid[time][var] = (short)mcgrid;
- return 1;
- }
- /**********************************************************************/
- /***** Input Functions *****/
- /**********************************************************************/
- /*
- * Read the header from a COMP* file and return results in the v5dstruct.
- * Input: f - the file descriptor
- * v - pointer to a v5dstruct.
- * Return: 1 = ok, 0 = error.
- */
- static int read_comp_header(int f, v5dstruct * v)
- {
- unsigned int id;
- /* reset file position to start of file */
- lseek(f, 0, SEEK_SET);
- /* read file ID */
- read_int4(f, (int *)&id);
- if (id == 0x80808080 || id == 0x80808081) {
- /* Older COMP5D format */
- int gridtimes, gridparms;
- int i, j, it, iv, nl;
- off_t gridsize;
- float hgttop, hgtinc;
- /*char *compgrid; */
- if (id == 0x80808080) {
- /* 20 vars, 300 times */
- gridtimes = 300;
- gridparms = 20;
- }
- else {
- /* 30 vars, 400 times */
- gridtimes = 400;
- gridparms = 30;
- }
- v->FirstGridPos = 12 * 4 + 8 * gridtimes + 4 * gridparms;
- read_int4(f, &v->NumTimes);
- read_int4(f, &v->NumVars);
- read_int4(f, &v->Nr);
- read_int4(f, &v->Nc);
- read_int4(f, &nl);
- for (i = 0; i < v->NumVars; i++) {
- v->Nl[i] = nl;
- v->LowLev[i] = 0;
- }
- read_float4(f, &v->ProjArgs[0]);
- read_float4(f, &v->ProjArgs[1]);
- read_float4(f, &hgttop);
- read_float4(f, &v->ProjArgs[2]);
- read_float4(f, &v->ProjArgs[3]);
- read_float4(f, &hgtinc);
- /*
- for (i=0;i<nl;i++) {
- v->Height[nl-i-1] = hgttop - i * hgtinc;
- }
- */
- v->VerticalSystem = 1;
- v->VertArgs[0] = hgttop - hgtinc * (nl - 1);
- v->VertArgs[1] = hgtinc;
- /* read dates and times */
- for (i = 0; i < gridtimes; i++) {
- read_int4(f, &j);
- v->DateStamp[i] = v5dDaysToYYDDD(j);
- }
- for (i = 0; i < gridtimes; i++) {
- read_int4(f, &j);
- v->TimeStamp[i] = v5dSecondsToHHMMSS(j);
- }
- /* read variable names */
- for (i = 0; i < gridparms; i++) {
- char name[4];
- read_bytes(f, name, 4);
- /* remove trailing spaces, if any */
- for (j = 3; j > 0; j--) {
- if (name[j] == ' ' || name[j] == 0)
- name[j] = 0;
- else
- break;
- }
- strncpy(v->VarName[i], name, 4);
- v->VarName[i][4] = 0;
- }
- gridsize = ((v->Nr * v->Nc * nl + 3) / 4) * 4;
- for (i = 0; i < v->NumVars; i++) {
- v->GridSize[i] = 8 + gridsize;
- }
- v->SumGridSizes = (8 + gridsize) * v->NumVars;
- /* read the grids and their ga,gb values to find min and max values */
- for (i = 0; i < v->NumVars; i++) {
- v->MinVal[i] = 999999.9;
- v->MaxVal[i] = -999999.9;
- }
- /*compgrid = (char *) G_malloc ( gridsize ); */
- for (it = 0; it < v->NumTimes; it++) {
- for (iv = 0; iv < v->NumVars; iv++) {
- float ga, gb;
- float min, max;
- read_float4(f, &ga);
- read_float4(f, &gb);
- /* skip ahead by 'gridsize' bytes */
- if (lseek(f, gridsize, SEEK_CUR) == -1) {
- printf("Error: Unexpected end of file, ");
- printf("file may be corrupted.\n");
- return 0;
- }
- min = -(125.0 + gb) / ga;
- max = (125.0 - gb) / ga;
- if (min < v->MinVal[iv])
- v->MinVal[iv] = min;
- if (max > v->MaxVal[iv])
- v->MaxVal[iv] = max;
- }
- }
- /*G_free ( compgrid ); */
- /* done */
- }
- else if (id == 0x80808082 || id == 0x80808083) {
- /* Newer COMP5D format */
- int gridtimes, gridsize;
- int it, iv, nl, i, j;
- float delta;
- read_int4(f, &gridtimes);
- read_int4(f, &v->NumVars);
- read_int4(f, &v->NumTimes);
- read_int4(f, &v->Nr);
- read_int4(f, &v->Nc);
- read_int4(f, &nl);
- for (i = 0; i < v->NumVars; i++) {
- v->Nl[i] = nl;
- }
- read_float4(f, &v->ProjArgs[2]);
- read_float4(f, &v->ProjArgs[3]);
- /* Read height and determine if equal spacing */
- v->VerticalSystem = 1;
- for (i = 0; i < nl; i++) {
- read_float4(f, &v->VertArgs[i]);
- if (i == 1) {
- delta = v->VertArgs[1] - v->VertArgs[0];
- }
- else if (i > 1) {
- if (delta != (v->VertArgs[i] - v->VertArgs[i - 1])) {
- v->VerticalSystem = 2;
- }
- }
- }
- if (v->VerticalSystem == 1) {
- v->VertArgs[1] = delta;
- }
- /* read variable names */
- for (iv = 0; iv < v->NumVars; iv++) {
- char name[8];
- read_bytes(f, name, 8);
- /* remove trailing spaces, if any */
- for (j = 7; j > 0; j--) {
- if (name[j] == ' ' || name[j] == 0)
- name[j] = 0;
- else
- break;
- }
- strncpy(v->VarName[iv], name, 8);
- v->VarName[iv][8] = 0;
- }
- for (iv = 0; iv < v->NumVars; iv++) {
- read_float4(f, &v->MinVal[iv]);
- }
- for (iv = 0; iv < v->NumVars; iv++) {
- read_float4(f, &v->MaxVal[iv]);
- }
- for (it = 0; it < gridtimes; it++) {
- read_int4(f, &j);
- v->TimeStamp[it] = v5dSecondsToHHMMSS(j);
- }
- for (it = 0; it < gridtimes; it++) {
- read_int4(f, &j);
- v->DateStamp[it] = v5dDaysToYYDDD(j);
- }
- for (it = 0; it < gridtimes; it++) {
- float nlat;
- read_float4(f, &nlat);
- if (it == 0)
- v->ProjArgs[0] = nlat;
- }
- for (it = 0; it < gridtimes; it++) {
- float wlon;
- read_float4(f, &wlon);
- if (it == 0)
- v->ProjArgs[1] = wlon;
- }
- /* calculate grid storage sizes */
- if (id == 0x80808082) {
- gridsize = nl * 2 * 4 + ((v->Nr * v->Nc * nl + 3) / 4) * 4;
- }
- else {
- /* McIDAS grid and file numbers present */
- gridsize = 8 + nl * 2 * 4 + ((v->Nr * v->Nc * nl + 3) / 4) * 4;
- }
- for (i = 0; i < v->NumVars; i++) {
- v->GridSize[i] = gridsize;
- }
- v->SumGridSizes = (off_t)gridsize * v->NumVars;
- /* read McIDAS numbers??? */
- /* size (in bytes) of all header info */
- v->FirstGridPos =
- 9 * 4 + v->Nl[0] * 4 + v->NumVars * 16 + gridtimes * 16;
- }
- v->CompressMode = 1; /* one byte per grid point */
- v->Projection = 1; /* Cylindrical equidistant */
- v->FileVersion[0] = 0;
- return 1;
- }
- /*
- * Read a compressed grid from a COMP* file.
- * Return: 1 = ok, 0 = error.
- */
- static int read_comp_grid(v5dstruct * v, int time, int var,
- float *ga, float *gb, void *compdata)
- {
- unsigned int pos;
- V5Dubyte bias;
- int i, n, nl;
- int f;
- V5Dubyte *compdata1 = (V5Dubyte *) compdata;
- f = v->FileDesc;
- /* move to position in file */
- pos = grid_position(v, time, var);
- lseek(f, pos, SEEK_SET);
- if (v->FileFormat == 0x80808083) {
- /* read McIDAS grid and file numbers */
- int mcfile, mcgrid;
- read_int4(f, &mcfile);
- read_int4(f, &mcgrid);
- v->McFile[time][var] = (short)mcfile;
- v->McGrid[time][var] = (short)mcgrid;
- }
- nl = v->Nl[var];
- if (v->FileFormat == 0x80808080 || v->FileFormat == 0x80808081) {
- /* single ga,gb pair for whole grid */
- float a, b;
- read_float4(f, &a);
- read_float4(f, &b);
- /* convert a, b to new v5d ga, gb values */
- for (i = 0; i < nl; i++) {
- if (a == 0.0) {
- ga[i] = gb[i] = 0.0;
- }
- else {
- gb[i] = (b + 128.0) / -a;
- ga[i] = 1.0 / a;
- }
- }
- bias = 128;
- }
- else {
- /* read ga, gb arrays */
- read_float4_array(f, ga, v->Nl[var]);
- read_float4_array(f, gb, v->Nl[var]);
- /* convert ga, gb values to v5d system */
- for (i = 0; i < nl; i++) {
- if (ga[i] == 0.0) {
- ga[i] = gb[i] = 0.0;
- }
- else {
- /*gb[i] = (gb[i]+125.0) / -ga[i]; */
- gb[i] = (gb[i] + 128.0) / -ga[i];
- ga[i] = 1.0 / ga[i];
- }
- }
- bias = 128; /* 125 ??? */
- }
- /* read compressed grid data */
- n = v->Nr * v->Nc * v->Nl[var];
- if (read_bytes(f, compdata1, n) != n)
- return 0;
- /* convert data values to v5d system */
- n = v->Nr * v->Nc * v->Nl[var];
- for (i = 0; i < n; i++) {
- compdata1[i] += bias;
- }
- return 1;
- }
- /*
- * Read a v5d file header.
- * Input: f - file opened for reading.
- * v - pointer to v5dstruct to store header info into.
- * Return: 1 = ok, 0 = error.
- */
- static int read_v5d_header(v5dstruct * v)
- {
- #define SKIP(N) lseek( f, N, SEEK_CUR )
- int end_of_header = 0;
- unsigned int id;
- int idlen, var, numargs;
- int f;
- f = v->FileDesc;
- /* first try to read the header id */
- read_int4(f, (int *)&id);
- read_int4(f, &idlen);
- if (id == TAG_ID && idlen == 0) {
- /* this is a v5d file */
- v->FileFormat = 0;
- }
- else if (id >= 0x80808080 && id <= 0x80808083) {
- /* this is an old COMP* file */
- v->FileFormat = id;
- return read_comp_header(f, v);
- }
- else {
- /* unknown file type */
- printf("Error: not a v5d file\n");
- return 0;
- }
- v->CompressMode = 1; /* default */
- while (!end_of_header) {
- int tag, length;
- int i, var, time, nl, lev;
- if (read_int4(f, &tag) < 1 || read_int4(f, &length) < 1) {
- printf("Error while reading header, premature EOF\n");
- return 0;
- }
- switch (tag) {
- case TAG_VERSION:
- assert(length == 10);
- read_bytes(f, v->FileVersion, 10);
- /* Check if reading a file made by a future version of Vis5D */
- if (strcmp(v->FileVersion, FILE_VERSION) > 0) {
- G_warning
- ("Trying to read a version %s file, you should upgrade Vis5D",
- v->FileVersion);
- }
- break;
- case TAG_NUMTIMES:
- assert(length == 4);
- read_int4(f, &v->NumTimes);
- break;
- case TAG_NUMVARS:
- assert(length == 4);
- read_int4(f, &v->NumVars);
- break;
- case TAG_VARNAME:
- assert(length == 14); /* 1 int + 10 char */
- read_int4(f, &var);
- read_bytes(f, v->VarName[var], 10);
- break;
- case TAG_NR:
- /* Number of rows for all variables */
- assert(length == 4);
- read_int4(f, &v->Nr);
- break;
- case TAG_NC:
- /* Number of columns for all variables */
- assert(length == 4);
- read_int4(f, &v->Nc);
- break;
- case TAG_NL:
- /* Number of levels for all variables */
- assert(length == 4);
- read_int4(f, &nl);
- for (i = 0; i < v->NumVars; i++) {
- v->Nl[i] = nl;
- }
- break;
- case TAG_NL_VAR:
- /* Number of levels for one variable */
- assert(length == 8);
- read_int4(f, &var);
- read_int4(f, &v->Nl[var]);
- break;
- case TAG_LOWLEV_VAR:
- /* Lowest level for one variable */
- assert(length == 8);
- read_int4(f, &var);
- read_int4(f, &v->LowLev[var]);
- break;
- case TAG_TIME:
- /* Time stamp for 1 timestep */
- assert(length == 8);
- read_int4(f, &time);
- read_int4(f, &v->TimeStamp[time]);
- break;
- case TAG_DATE:
- /* Date stamp for 1 timestep */
- assert(length == 8);
- read_int4(f, &time);
- read_int4(f, &v->DateStamp[time]);
- break;
- case TAG_MINVAL:
- /* Minimum value for a variable */
- assert(length == 8);
- read_int4(f, &var);
- read_float4(f, &v->MinVal[var]);
- break;
- case TAG_MAXVAL:
- /* Maximum value for a variable */
- assert(length == 8);
- read_int4(f, &var);
- read_float4(f, &v->MaxVal[var]);
- break;
- case TAG_COMPRESS:
- /* Compress mode */
- assert(length == 4);
- read_int4(f, &v->CompressMode);
- break;
- case TAG_UNITS:
- /* physical units */
- assert(length == 24);
- read_int4(f, &var);
- read_bytes(f, v->Units[var], 20);
- break;
- /*
- * Vertical coordinate system
- */
- case TAG_VERTICAL_SYSTEM:
- assert(length == 4);
- read_int4(f, &v->VerticalSystem);
- if (v->VerticalSystem < 0 || v->VerticalSystem > 3) {
- printf("Error: bad vertical coordinate system: %d\n",
- v->VerticalSystem);
- }
- break;
- case TAG_VERT_ARGS:
- read_int4(f, &numargs);
- assert(numargs <= MAXVERTARGS);
- read_float4_array(f, v->VertArgs, numargs);
- assert(length == numargs * 4 + 4);
- break;
- case TAG_HEIGHT:
- /* height of a grid level */
- assert(length == 8);
- read_int4(f, &lev);
- read_float4(f, &v->VertArgs[lev]);
- break;
- case TAG_BOTTOMBOUND:
- assert(length == 4);
- read_float4(f, &v->VertArgs[0]);
- break;
- case TAG_LEVINC:
- assert(length == 4);
- read_float4(f, &v->VertArgs[1]);
- break;
- /*
- * Map projection information
- */
- case TAG_PROJECTION:
- assert(length == 4);
- read_int4(f, &v->Projection);
- if (v->Projection < 0 || v->Projection > 4) { /* WLH 4-21-95 */
- printf("Error while reading header, bad projection (%d)\n",
- v->Projection);
- return 0;
- }
- break;
- case TAG_PROJ_ARGS:
- read_int4(f, &numargs);
- assert(numargs <= MAXPROJARGS);
- read_float4_array(f, v->ProjArgs, numargs);
- assert(length == 4 * numargs + 4);
- break;
- case TAG_NORTHBOUND:
- assert(length == 4);
- if (v->Projection == 0 || v->Projection == 1 ||
- v->Projection == 4) {
- read_float4(f, &v->ProjArgs[0]);
- }
- else {
- SKIP(4);
- }
- break;
- case TAG_WESTBOUND:
- assert(length == 4);
- if (v->Projection == 0 || v->Projection == 1 ||
- v->Projection == 4) {
- read_float4(f, &v->ProjArgs[1]);
- }
- else {
- SKIP(4);
- }
- break;
- case TAG_ROWINC:
- assert(length == 4);
- if (v->Projection == 0 || v->Projection == 1 ||
- v->Projection == 4) {
- read_float4(f, &v->ProjArgs[2]);
- }
- else {
- SKIP(4);
- }
- break;
- case TAG_COLINC:
- assert(length == 4);
- if (v->Projection == 0 || v->Projection == 1 ||
- v->Projection == 4) {
- read_float4(f, &v->ProjArgs[3]);
- }
- else if (v->Projection == 2) {
- read_float4(f, &v->ProjArgs[5]);
- }
- else if (v->Projection == 3) {
- read_float4(f, &v->ProjArgs[4]);
- }
- else {
- SKIP(4);
- }
- break;
- case TAG_LAT1:
- assert(length == 4);
- if (v->Projection == 2) {
- read_float4(f, &v->ProjArgs[0]);
- }
- else {
- SKIP(4);
- }
- break;
- case TAG_LAT2:
- assert(length == 4);
- if (v->Projection == 2) {
- read_float4(f, &v->ProjArgs[1]);
- }
- else {
- SKIP(4);
- }
- break;
- case TAG_POLE_ROW:
- assert(length == 4);
- if (v->Projection == 2) {
- read_float4(f, &v->ProjArgs[2]);
- }
- else {
- SKIP(4);
- }
- break;
- case TAG_POLE_COL:
- assert(length == 4);
- if (v->Projection == 2) {
- read_float4(f, &v->ProjArgs[3]);
- }
- else {
- SKIP(4);
- }
- break;
- case TAG_CENTLON:
- assert(length == 4);
- if (v->Projection == 2) {
- read_float4(f, &v->ProjArgs[4]);
- }
- else if (v->Projection == 3) {
- read_float4(f, &v->ProjArgs[1]);
- }
- else if (v->Projection == 4) { /* WLH 4-21-95 */
- read_float4(f, &v->ProjArgs[5]);
- }
- else {
- SKIP(4);
- }
- break;
- case TAG_CENTLAT:
- assert(length == 4);
- if (v->Projection == 3) {
- read_float4(f, &v->ProjArgs[0]);
- }
- else if (v->Projection == 4) { /* WLH 4-21-95 */
- read_float4(f, &v->ProjArgs[4]);
- }
- else {
- SKIP(4);
- }
- break;
- case TAG_CENTROW:
- assert(length == 4);
- if (v->Projection == 3) {
- read_float4(f, &v->ProjArgs[2]);
- }
- else {
- SKIP(4);
- }
- break;
- case TAG_CENTCOL:
- assert(length == 4);
- if (v->Projection == 3) {
- read_float4(f, &v->ProjArgs[3]);
- }
- else {
- SKIP(4);
- }
- break;
- case TAG_ROTATION:
- assert(length == 4);
- if (v->Projection == 4) { /* WLH 4-21-95 */
- read_float4(f, &v->ProjArgs[6]);
- }
- else {
- SKIP(4);
- }
- break;
- case TAG_END:
- /* end of header */
- end_of_header = 1;
- lseek(f, length, SEEK_CUR);
- break;
- default:
- /* unknown tag, skip to next tag */
- printf("Unknown tag: %d length=%d\n", tag, length);
- lseek(f, length, SEEK_CUR);
- break;
- }
- }
- v5dVerifyStruct(v);
- /* Now we're ready to read the grid data */
- /* Save current file pointer */
- v->FirstGridPos = ltell(f);
- /* compute grid sizes */
- v->SumGridSizes = 0;
- for (var = 0; var < v->NumVars; var++) {
- v->GridSize[var] = 8 * v->Nl[var] + v5dSizeofGrid(v, 0, var);
- v->SumGridSizes += v->GridSize[var];
- }
- return 1;
- #undef SKIP
- }
- /*
- * Open a v5d file for reading.
- * Input: filename - name of v5d file to open
- * v - pointer to a v5dstruct in which to put header info or NULL
- * if a struct should be dynamically allocated.
- * Return: NULL if error, else v or a pointer to a new v5dstruct if v was NULL
- */
- v5dstruct *v5dOpenFile(const char *filename, v5dstruct * v)
- {
- int fd;
- fd = open(filename, O_RDONLY);
- if (fd == -1) {
- /* error */
- return 0;
- }
- if (v) {
- v5dInitStruct(v);
- }
- else {
- v = v5dNewStruct();
- if (!v) {
- return NULL;
- }
- }
- v->FileDesc = fd;
- v->Mode = 'r';
- if (read_v5d_header(v)) {
- return v;
- }
- else {
- return NULL;
- }
- }
- /*
- * Read a compressed grid from a v5d file.
- * Input: v - pointer to v5dstruct describing the file
- * time, var - which timestep and variable
- * ga, gb - arrays to store grid (de)compression values
- * compdata - address of where to store compressed grid data.
- * Return: 1 = ok, 0 = error.
- */
- int v5dReadCompressedGrid(v5dstruct * v, int time, int var,
- float *ga, float *gb, void *compdata)
- {
- int n, k;
- off_t pos;
- if (time < 0 || time >= v->NumTimes) {
- printf("Error in v5dReadCompressedGrid: bad timestep argument (%d)\n",
- time);
- return 0;
- }
- if (var < 0 || var >= v->NumVars) {
- printf("Error in v5dReadCompressedGrid: bad var argument (%d)\n",
- var);
- return 0;
- }
- if (v->FileFormat) {
- /* old COMP* file */
- return read_comp_grid(v, time, var, ga, gb, compdata);
- }
- /* move to position in file */
- pos = grid_position(v, time, var);
- lseek(v->FileDesc, pos, SEEK_SET);
- /* read ga, gb arrays */
- read_float4_array(v->FileDesc, ga, v->Nl[var]);
- read_float4_array(v->FileDesc, gb, v->Nl[var]);
- /* read compressed grid data */
- n = v->Nr * v->Nc * v->Nl[var];
- if (v->CompressMode == 1) {
- k = read_block(v->FileDesc, compdata, n, 1) == n;
- }
- else if (v->CompressMode == 2) {
- k = read_block(v->FileDesc, compdata, n, 2) == n;
- }
- else if (v->CompressMode == 4) {
- k = read_block(v->FileDesc, compdata, n, 4) == n;
- }
- if (!k) {
- /* error */
- printf("Error in v5dReadCompressedGrid: read failed, bad file?\n");
- }
- return k;
- /*
- n = v->Nr * v->Nc * v->Nl[var] * v->CompressMode;
- if (read( v->FileDesc, compdata, n )==n)
- return 1;
- else
- return 0;
- */
- }
- /*
- * Read a grid from a v5d file, decompress it and return it.
- * Input: v - pointer to v5dstruct describing file header
- * time, var - which timestep and variable.
- * data - address of buffer to put grid data
- * Output: data - the grid data
- * Return: 1 = ok, 0 = error.
- */
- int v5dReadGrid(v5dstruct * v, int time, int var, float data[])
- {
- float ga[MAXLEVELS], gb[MAXLEVELS];
- void *compdata;
- int bytes;
- if (time < 0 || time >= v->NumTimes) {
- printf("Error in v5dReadGrid: bad timestep argument (%d)\n", time);
- return 0;
- }
- if (var < 0 || var >= v->NumVars) {
- printf("Error in v5dReadGrid: bad variable argument (%d)\n", var);
- return 0;
- }
- /* allocate compdata buffer */
- if (v->CompressMode == 1) {
- bytes = v->Nr * v->Nc * v->Nl[var] * (int)sizeof(unsigned char);
- }
- else if (v->CompressMode == 2) {
- bytes = v->Nr * v->Nc * v->Nl[var] * (int)sizeof(unsigned short);
- }
- else if (v->CompressMode == 4) {
- bytes = v->Nr * v->Nc * v->Nl[var] * (int)sizeof(float);
- }
- compdata = (void *)G_malloc(bytes);
- if (!compdata) {
- printf("Error in v5dReadGrid: out of memory (needed %d bytes)\n",
- bytes);
- return 0;
- }
- /* read the compressed data */
- if (!v5dReadCompressedGrid(v, time, var, ga, gb, compdata)) {
- return 0;
- }
- /* decompress the data */
- v5dDecompressGrid(v->Nr, v->Nc, v->Nl[var], v->CompressMode,
- compdata, ga, gb, data);
- /* free compdata */
- G_free(compdata);
- return 1;
- }
- /**********************************************************************/
- /***** Output Functions *****/
- /**********************************************************************/
- static int write_tag(v5dstruct * v, int tag, int length, int newfile)
- {
- if (!newfile) {
- /* have to check that there's room in header to write this tagged item */
- if (v->CurPos + 8 + length > v->FirstGridPos) {
- printf("Error: out of header space!\n");
- /* Out of header space! */
- return 0;
- }
- }
- if (write_int4(v->FileDesc, tag) == 0)
- return 0;
- if (write_int4(v->FileDesc, length) == 0)
- return 0;
- v->CurPos += 8 + length;
- return 1;
- }
- /*
- * Write the information in the given v5dstruct as a v5d file header.
- * Note that the current file position is restored when this function
- * returns normally.
- * Input: f - file already open for writing
- * v - pointer to v5dstruct
- * Return: 1 = ok, 0 = error.
- */
- static int write_v5d_header(v5dstruct * v)
- {
- int var, time, maxnl;
- off_t filler;
- int f;
- int newfile;
- if (v->FileFormat != 0) {
- printf("Error: v5d library can't write comp5d format files.\n");
- return 0;
- }
- f = v->FileDesc;
- if (!v5dVerifyStruct(v))
- return 0;
- /* Determine if we're writing to a new file */
- if (v->FirstGridPos == 0) {
- newfile = 1;
- }
- else {
- newfile = 0;
- }
- /* compute grid sizes */
- v->SumGridSizes = 0;
- for (var = 0; var < v->NumVars; var++) {
- v->GridSize[var] = 8 * v->Nl[var] + v5dSizeofGrid(v, 0, var);
- v->SumGridSizes += v->GridSize[var];
- }
- /* set file pointer to start of file */
- lseek(f, 0, SEEK_SET);
- v->CurPos = 0;
- /*
- * Write the tagged header info
- */
- #define WRITE_TAG( V, T, L ) if (!write_tag(V,T,L,newfile)) return 0;
- /* ID */
- WRITE_TAG(v, TAG_ID, 0);
- /* File Version */
- WRITE_TAG(v, TAG_VERSION, 10);
- write_bytes(f, FILE_VERSION, 10);
- /* Number of timesteps */
- WRITE_TAG(v, TAG_NUMTIMES, 4);
- write_int4(f, v->NumTimes);
- /* Number of variables */
- WRITE_TAG(v, TAG_NUMVARS, 4);
- write_int4(f, v->NumVars);
- /* Names of variables */
- for (var = 0; var < v->NumVars; var++) {
- WRITE_TAG(v, TAG_VARNAME, 14);
- write_int4(f, var);
- write_bytes(f, v->VarName[var], 10);
- }
- /* Physical Units */
- for (var = 0; var < v->NumVars; var++) {
- WRITE_TAG(v, TAG_UNITS, 24);
- write_int4(f, var);
- write_bytes(f, v->Units[var], 20);
- }
- /* Date and time of each timestep */
- for (time = 0; time < v->NumTimes; time++) {
- WRITE_TAG(v, TAG_TIME, 8);
- write_int4(f, time);
- write_int4(f, v->TimeStamp[time]);
- WRITE_TAG(v, TAG_DATE, 8);
- write_int4(f, time);
- write_int4(f, v->DateStamp[time]);
- }
- /* Number of rows */
- WRITE_TAG(v, TAG_NR, 4);
- write_int4(f, v->Nr);
- /* Number of columns */
- WRITE_TAG(v, TAG_NC, 4);
- write_int4(f, v->Nc);
- /* Number of levels, compute maxnl */
- maxnl = 0;
- for (var = 0; var < v->NumVars; var++) {
- WRITE_TAG(v, TAG_NL_VAR, 8);
- write_int4(f, var);
- write_int4(f, v->Nl[var]);
- WRITE_TAG(v, TAG_LOWLEV_VAR, 8);
- write_int4(f, var);
- write_int4(f, v->LowLev[var]);
- if (v->Nl[var] + v->LowLev[var] > maxnl) {
- maxnl = v->Nl[var] + v->LowLev[var];
- }
- }
- /* Min/Max values */
- for (var = 0; var < v->NumVars; var++) {
- WRITE_TAG(v, TAG_MINVAL, 8);
- write_int4(f, var);
- write_float4(f, v->MinVal[var]);
- WRITE_TAG(v, TAG_MAXVAL, 8);
- write_int4(f, var);
- write_float4(f, v->MaxVal[var]);
- }
- /* Compress mode */
- WRITE_TAG(v, TAG_COMPRESS, 4);
- write_int4(f, v->CompressMode);
- /* Vertical Coordinate System */
- WRITE_TAG(v, TAG_VERTICAL_SYSTEM, 4);
- write_int4(f, v->VerticalSystem);
- WRITE_TAG(v, TAG_VERT_ARGS, 4 + 4 * MAXVERTARGS);
- write_int4(f, MAXVERTARGS);
- write_float4_array(f, v->VertArgs, MAXVERTARGS);
- /* Map Projection */
- WRITE_TAG(v, TAG_PROJECTION, 4);
- write_int4(f, v->Projection);
- WRITE_TAG(v, TAG_PROJ_ARGS, 4 + 4 * MAXPROJARGS);
- write_int4(f, MAXPROJARGS);
- write_float4_array(f, v->ProjArgs, MAXPROJARGS);
- /* write END tag */
- if (newfile) {
- /* We're writing to a brand new file. Reserve 10000 bytes */
- /* for future header growth. */
- WRITE_TAG(v, TAG_END, 10000);
- lseek(f, 10000, SEEK_CUR);
- /* Let file pointer indicate where first grid is stored */
- v->FirstGridPos = ltell(f);
- }
- else {
- /* we're rewriting a header */
- filler = v->FirstGridPos - ltell(f);
- WRITE_TAG(v, TAG_END, filler - 8);
- }
- #undef WRITE_TAG
- return 1;
- }
- /*
- * Open a v5d file for writing. If the named file already exists,
- * it will be deleted.
- * Input: filename - name of v5d file to create.
- * v - pointer to v5dstruct with the header info to write.
- * Return: 1 = ok, 0 = error.
- */
- int v5dCreateFile(const char *filename, v5dstruct * v)
- {
- mode_t mask;
- int fd;
- mask = 0666;
- fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, mask);
- if (fd == -1) {
- printf("Error in v5dCreateFile: open failed\n");
- v->FileDesc = -1;
- v->Mode = 0;
- return 0;
- }
- else {
- /* ok */
- v->FileDesc = fd;
- v->Mode = 'w';
- /* write header and return status */
- return write_v5d_header(v);
- }
- }
- /*
- * Open a v5d file for updating/appending and read the header info.
- * Input: filename - name of v5d file to open for updating.
- * v - pointer to v5dstruct in which the file header info will be
- * put. If v is NULL a v5dstruct will be allocated and returned.
- * Return: NULL if error, else v or a pointer to a new v5dstruct if v as NULL
- */
- v5dstruct *v5dUpdateFile(const char *filename, v5dstruct * v)
- {
- int fd;
- fd = open(filename, O_RDWR);
- if (fd == -1) {
- return NULL;
- }
- if (!v) {
- v = v5dNewStruct();
- if (!v) {
- return NULL;
- }
- }
- v->FileDesc = fd;
- v->Mode = 'w';
- if (read_v5d_header(v)) {
- return v;
- }
- else {
- return NULL;
- }
- }
- /*
- * Write a compressed grid to a v5d file.
- * Input: v - pointer to v5dstruct describing the file
- * time, var - which timestep and variable
- * ga, gb - the GA and GB (de)compression value arrays
- * compdata - address of array of compressed data values
- * Return: 1 = ok, 0 = error.
- */
- int v5dWriteCompressedGrid(const v5dstruct * v, int time, int var,
- const float *ga, const float *gb,
- const void *compdata)
- {
- int n, k;
- off_t pos;
- /* simple error checks */
- if (v->Mode != 'w') {
- printf("Error in v5dWriteCompressedGrid: file opened for reading,");
- printf(" not writing.\n");
- return 0;
- }
- if (time < 0 || time >= v->NumTimes) {
- printf
- ("Error in v5dWriteCompressedGrid: bad timestep argument (%d)\n",
- time);
- return 0;
- }
- if (var < 0 || var >= v->NumVars) {
- printf
- ("Error in v5dWriteCompressedGrid: bad variable argument (%d)\n",
- var);
- return 0;
- }
- /* move to position in file */
- pos = grid_position(v, time, var);
- if (lseek(v->FileDesc, pos, SEEK_SET) < 0) {
- /* lseek failed, return error */
- printf
- ("Error in v5dWrite[Compressed]Grid: seek failed, disk full?\n");
- return 0;
- }
- /* write ga, gb arrays */
- k = 0;
- if (write_float4_array(v->FileDesc, ga, v->Nl[var]) == v->Nl[var] &&
- write_float4_array(v->FileDesc, gb, v->Nl[var]) == v->Nl[var]) {
- /* write compressed grid data (k=1=OK, k=0=Error) */
- n = v->Nr * v->Nc * v->Nl[var];
- if (v->CompressMode == 1) {
- k = write_block(v->FileDesc, compdata, n, 1) == n;
- }
- else if (v->CompressMode == 2) {
- k = write_block(v->FileDesc, compdata, n, 2) == n;
- }
- else if (v->CompressMode == 4) {
- k = write_block(v->FileDesc, compdata, n, 4) == n;
- }
- }
- if (k == 0) {
- /* Error while writing */
- printf
- ("Error in v5dWrite[Compressed]Grid: write failed, disk full?\n");
- }
- return k;
- /*
- n = v->Nr * v->Nc * v->Nl[var] * v->CompressMode;
- if (write_bytes( v->FileDesc, compdata, n )!=n) {
- printf("Error in v5dWrite[Compressed]Grid: write failed, disk full?\n");
- return 0;
- }
- else {
- return 1;
- }
- */
- }
- /*
- * Compress a grid and write it to a v5d file.
- * Input: v - pointer to v5dstruct describing the file
- * time, var - which timestep and variable (starting at 0)
- * data - address of uncompressed grid data
- * Return: 1 = ok, 0 = error.
- */
- int v5dWriteGrid(v5dstruct * v, int time, int var, const float data[])
- {
- float ga[MAXLEVELS], gb[MAXLEVELS];
- void *compdata;
- int n, bytes;
- float min, max;
- if (v->Mode != 'w') {
- printf("Error in v5dWriteGrid: file opened for reading,");
- printf(" not writing.\n");
- return 0;
- }
- if (time < 0 || time >= v->NumTimes) {
- printf("Error in v5dWriteGrid: bad timestep argument (%d)\n", time);
- return 0;
- }
- if (var < 0 || var >= v->NumVars) {
- printf("Error in v5dWriteGrid: bad variable argument (%d)\n", var);
- return 0;
- }
- /* allocate compdata buffer */
- if (v->CompressMode == 1) {
- bytes = v->Nr * v->Nc * v->Nl[var] * (int)sizeof(unsigned char);
- }
- else if (v->CompressMode == 2) {
- bytes = v->Nr * v->Nc * v->Nl[var] * (int)sizeof(unsigned short);
- }
- else if (v->CompressMode == 4) {
- bytes = v->Nr * v->Nc * v->Nl[var] * (int)sizeof(float);
- }
- compdata = (void *)G_malloc(bytes);
- if (!compdata) {
- printf("Error in v5dWriteGrid: out of memory (needed %d bytes)\n",
- bytes);
- return 0;
- }
- /* compress the grid data */
- v5dCompressGrid(v->Nr, v->Nc, v->Nl[var], v->CompressMode, data,
- compdata, ga, gb, &min, &max);
- /* update min and max value */
- if (min < v->MinVal[var])
- v->MinVal[var] = min;
- if (max > v->MaxVal[var])
- v->MaxVal[var] = max;
- /* write the compressed grid */
- n = v5dWriteCompressedGrid(v, time, var, ga, gb, compdata);
- /* free compdata */
- G_free(compdata);
- return n;
- }
- /*
- * Close a v5d file which was opened with open_v5d_file() or
- * create_v5d_file().
- * Input: f - file descriptor
- * Return: 1 = ok, 0 = error
- */
- int v5dCloseFile(v5dstruct * v)
- {
- int status = 1;
- if (v->Mode == 'w') {
- /* rewrite header because writing grids updates the minval and */
- /* maxval fields */
- lseek(v->FileDesc, 0, SEEK_SET);
- status = write_v5d_header(v);
- lseek(v->FileDesc, 0, SEEK_END);
- close(v->FileDesc);
- }
- else if (v->Mode == 'r') {
- /* just close the file */
- close(v->FileDesc);
- }
- else {
- printf("Error in v5dCloseFile: bad v5dstruct argument\n");
- return 0;
- }
- v->FileDesc = -1;
- v->Mode = 0;
- return status;
- }
- /**********************************************************************/
- /***** Simple v5d file writing functions. *****/
- /**********************************************************************/
- static v5dstruct *Simple = NULL;
- /*
- * Create a new v5d file specifying both a map projection and vertical
- * coordinate system. See README file for argument details.
- * Return: 1 = ok, 0 = error.
- */
- int v5dCreate(const char *name, int numtimes, int numvars,
- int nr, int nc, const int nl[],
- const char varname[MAXVARS][10],
- const int timestamp[], const int datestamp[],
- int compressmode,
- int projection,
- const float proj_args[], int vertical, const float vert_args[])
- {
- int var, time, maxnl, i;
- /* initialize the v5dstruct */
- Simple = v5dNewStruct();
- Simple->NumTimes = numtimes;
- Simple->NumVars = numvars;
- Simple->Nr = nr;
- Simple->Nc = nc;
- maxnl = nl[0];
- for (var = 0; var < numvars; var++) {
- if (nl[var] > maxnl) {
- maxnl = nl[var];
- }
- Simple->Nl[var] = nl[var];
- Simple->LowLev[var] = 0;
- strncpy(Simple->VarName[var], varname[var], 10);
- Simple->VarName[var][9] = 0;
- }
- /* time and date for each timestep */
- for (time = 0; time < numtimes; time++) {
- Simple->TimeStamp[time] = timestamp[time];
- Simple->DateStamp[time] = datestamp[time];
- }
- Simple->CompressMode = compressmode;
- /* Map projection and vertical coordinate system */
- Simple->Projection = projection;
- memcpy(Simple->ProjArgs, proj_args, MAXPROJARGS * sizeof(float));
- Simple->VerticalSystem = vertical;
- if (vertical == 3) {
- /* convert pressures to heights */
- for (i = 0; i < MAXVERTARGS; i++) {
- if (vert_args[i] > 0.000001) {
- Simple->VertArgs[i] = pressure_to_height(vert_args[i]);
- }
- else
- Simple->VertArgs[i] = 0.0;
- }
- }
- else {
- memcpy(Simple->VertArgs, vert_args, MAXVERTARGS * sizeof(float));
- }
- /* create the file */
- if (v5dCreateFile(name, Simple) == 0) {
- printf("Error in v5dCreateSimpleFile: unable to create %s\n", name);
- return 0;
- }
- else {
- return 1;
- }
- }
- /*
- * Create a new v5d file using minimal information.
- * Return: 1 = ok, 0 = error. See README file for argument details.
- */
- int v5dCreateSimple(const char *name, int numtimes, int numvars,
- int nr, int nc, int nl,
- const char varname[MAXVARS][10],
- const int timestamp[], const int datestamp[],
- float northlat, float latinc,
- float westlon, float loninc,
- float bottomhgt, float hgtinc)
- {
- int nlvar[MAXVARS];
- int compressmode, projection, vertical;
- float proj_args[100], vert_args[MAXLEVELS];
- int i;
- for (i = 0; i < numvars; i++) {
- nlvar[i] = nl;
- }
- compressmode = 1;
- projection = 1;
- proj_args[0] = northlat;
- proj_args[1] = westlon;
- proj_args[2] = latinc;
- proj_args[3] = loninc;
- vertical = 1;
- vert_args[0] = bottomhgt;
- vert_args[1] = hgtinc;
- return v5dCreate(name, numtimes, numvars, nr, nc, nlvar,
- varname, timestamp, datestamp, compressmode,
- projection, proj_args, vertical, vert_args);
- }
- /*
- * Set lowest levels for each variable (other than default of 0).
- * Input: lowlev - array [NumVars] of ints
- * Return: 1 = ok, 0 = error
- */
- int v5dSetLowLev(int lowlev[])
- {
- int var;
- if (Simple) {
- for (var = 0; var < Simple->NumVars; var++) {
- Simple->LowLev[var] = lowlev[var];
- }
- return 1;
- }
- else {
- printf("Error: must call v5dCreate before v5dSetLowLev\n");
- return 0;
- }
- }
- /*
- * Set the units for a variable.
- * Input: var - a variable in [1,NumVars]
- * units - a string
- * Return: 1 = ok, 0 = error
- */
- int v5dSetUnits(int var, const char *units)
- {
- if (Simple) {
- if (var >= 1 && var <= Simple->NumVars) {
- strncpy(Simple->Units[var - 1], units, 19);
- Simple->Units[var - 1][19] = 0;
- return 1;
- }
- else {
- printf("Error: bad variable number in v5dSetUnits\n");
- return 0;
- }
- }
- else {
- printf("Error: must call v5dCreate before v5dSetUnits\n");
- return 0;
- }
- }
- /*
- * Write a grid to a v5d file.
- * Input: time - timestep in [1,NumTimes]
- * var - timestep in [1,NumVars]
- * data - array [nr*nc*nl] of floats
- * Return: 1 = ok, 0 = error
- */
- int v5dWrite(int time, int var, const float data[])
- {
- if (Simple) {
- if (time < 1 || time > Simple->NumTimes) {
- printf("Error in v5dWrite: bad timestep number: %d\n", time);
- return 0;
- }
- if (var < 1 || var > Simple->NumVars) {
- printf("Error in v5dWrite: bad variable number: %d\n", var);
- }
- return v5dWriteGrid(Simple, time - 1, var - 1, data);
- }
- else {
- printf("Error: must call v5dCreate before v5dWrite\n");
- return 0;
- }
- }
- /*
- * Close a v5d file after the last grid has been written to it.
- * Return: 1 = ok, 0 = error
- */
- int v5dClose(void)
- {
- if (Simple) {
- int ok = v5dCloseFile(Simple);
- v5dFreeStruct(Simple);
- return ok;
- }
- else {
- printf("Error: v5dClose: no file to close\n");
- return 0;
- }
- }
- /**********************************************************************/
- /***** FORTRAN-callable simple output *****/
- /**********************************************************************/
- /*
- * Create a v5d file. See README file for argument descriptions.
- * Return: 1 = ok, 0 = error.
- */
- #ifdef UNDERSCORE
- int v5dcreate_
- #else
- # ifdef _CRAY
- int V5DCREATE
- # else
- int v5dcreate
- # endif
- #endif
-
- (const char *name, const int *numtimes, const int *numvars,
- const int *nr, const int *nc, const int nl[],
- const char varname[][10],
- const int timestamp[], const int datestamp[],
- const int *compressmode,
- const int *projection,
- const float proj_args[], const int *vertical, const float vert_args[])
- {
- char filename[100];
- char names[MAXVARS][10];
- int i, maxnl, args;
- /* copy name to filename and remove trailing spaces if any */
- copy_string(filename, name, 100);
- /*
- * Check for uninitialized arguments
- */
- if (*numtimes < 1) {
- printf("Error: numtimes invalid\n");
- return 0;
- }
- if (*numvars < 1) {
- printf("Error: numvars invalid\n");
- return 0;
- }
- if (*nr < 2) {
- printf("Error: nr invalid\n");
- return 0;
- }
- if (*nc < 2) {
- printf("Error: nc invalid\n");
- return 0;
- }
- maxnl = 0;
- for (i = 0; i < *numvars; i++) {
- if (nl[i] < 1) {
- printf("Error: nl(%d) invalid\n", i + 1);
- return 0;
- }
- if (nl[i] > maxnl) {
- maxnl = nl[i];
- }
- }
- for (i = 0; i < *numvars; i++) {
- if (copy_string2(names[i], varname[i], 10) == 0) {
- printf("Error: uninitialized varname(%d)\n", i + 1);
- return 0;
- }
- }
- for (i = 0; i < *numtimes; i++) {
- if (timestamp[i] < 0) {
- printf("Error: times(%d) invalid\n", i + 1);
- return 0;
- }
- if (datestamp[i] < 0) {
- printf("Error: dates(%d) invalid\n", i + 1);
- return 0;
- }
- }
- if (*compressmode != 1 && *compressmode != 2 && *compressmode != 4) {
- printf("Error: compressmode invalid\n");
- return 0;
- }
- switch (*projection) {
- case 0:
- args = 4;
- break;
- case 1:
- args = 0;
- if (IS_MISSING(proj_args[0])) {
- printf("Error: northlat (proj_args(1)) invalid\n");
- return 0;
- }
- if (IS_MISSING(proj_args[1])) {
- printf("Error: westlon (proj_args(2)) invalid\n");
- return 0;
- }
- if (IS_MISSING(proj_args[2])) {
- printf("Error: latinc (proj_args(3)) invalid\n");
- return 0;
- }
- if (IS_MISSING(proj_args[3])) {
- printf("Error: loninc (proj_args(4)) invalid\n");
- return 0;
- }
- break;
- case 2:
- args = 6;
- break;
- case 3:
- args = 5;
- break;
- case 4:
- args = 7;
- break;
- default:
- args = 0;
- printf("Error: projection invalid\n");
- return 0;
- }
- for (i = 0; i < args; i++) {
- if (IS_MISSING(proj_args[i])) {
- printf("Error: proj_args(%d) invalid\n", i + 1);
- return 0;
- }
- }
- switch (*vertical) {
- case 0:
- /* WLH 31 Oct 96 - just fall through
- args = 4;
- break;
- */
- case 1:
- args = 0;
- if (IS_MISSING(vert_args[0])) {
- printf("Error: bottomhgt (vert_args(1)) invalid\n");
- return 0;
- }
- if (IS_MISSING(vert_args[1])) {
- printf("Error: hgtinc (vert_args(2)) invalid\n");
- return 0;
- }
- break;
- case 2:
- case 3:
- args = maxnl;
- break;
- default:
- args = 0;
- printf("Error: vertical invalid\n");
- return 0;
- }
- for (i = 0; i < args; i++) {
- if (IS_MISSING(vert_args[i])) {
- printf("Error: vert_args(%d) invalid\n", i + 1);
- return 0;
- }
- }
- return v5dCreate(filename, *numtimes, *numvars, *nr, *nc, nl,
- (const char (*)[10])names, timestamp, datestamp,
- *compressmode,
- *projection, proj_args, *vertical, vert_args);
- }
- /*
- * Create a simple v5d file. See README file for argument descriptions.
- * Return: 1 = ok, 0 = error.
- */
- #ifdef UNDERSCORE
- int v5dcreatesimple_
- #else
- # ifdef _CRAY
- int V5DCREATESIMPLE
- # else
- int v5dcreatesimple
- # endif
- #endif
-
- (const char *name, const int *numtimes, const int *numvars,
- const int *nr, const int *nc, const int *nl,
- const char varname[][10],
- const int timestamp[], const int datestamp[],
- const float *northlat, const float *latinc,
- const float *westlon, const float *loninc,
- const float *bottomhgt, const float *hgtinc)
- {
- int compressmode, projection, vertical;
- float projarg[100], vertarg[MAXLEVELS];
- int varnl[MAXVARS];
- int i;
- for (i = 0; i < MAXVARS; i++) {
- varnl[i] = *nl;
- }
- compressmode = 1;
- projection = 1;
- projarg[0] = *northlat;
- projarg[1] = *westlon;
- projarg[2] = *latinc;
- projarg[3] = *loninc;
- vertical = 1;
- vertarg[0] = *bottomhgt;
- vertarg[1] = *hgtinc;
- #ifdef UNDERSCORE
- return v5dcreate_
- #else
- # ifdef _CRAY
- return V5DCREATE
- # else
- return v5dcreate
- # endif
- #endif
- (name, numtimes, numvars, nr, nc, varnl,
- varname, timestamp, datestamp, &compressmode,
- &projection, projarg, &vertical, vertarg);
- }
- /*
- * Set lowest levels for each variable (other than default of 0).
- * Input: lowlev - array [NumVars] of ints
- * Return: 1 = ok, 0 = error
- */
- #ifdef UNDERSCORE
- int v5dsetlowlev_
- #else
- # ifdef _CRAY
- int V5DSETLOWLEV
- # else
- int v5dsetlowlev
- # endif
- #endif
- (int *lowlev)
- {
- return v5dSetLowLev(lowlev);
- }
- /*
- * Set the units for a variable.
- * Input: var - variable number in [1,NumVars]
- * units - a character string
- * Return: 1 = ok, 0 = error
- */
- #ifdef UNDERSCORE
- int v5dsetunits_
- #else
- # ifdef _CRAY
- int V5DSETUNITS
- # else
- int v5dsetunits
- # endif
- #endif
- (int *var, char *name)
- {
- return v5dSetUnits(*var, name);
- }
- /*
- * Write a grid of data to the file.
- * Input: time - timestep in [1,NumTimes]
- * var - timestep in [1,NumVars]
- * data - array [nr*nc*nl] of floats
- * Return: 1 = ok, 0 = error
- */
- #ifdef UNDERSCORE
- int v5dwrite_
- #else
- # ifdef _CRAY
- int V5DWRITE
- # else
- int v5dwrite
- # endif
- #endif
- (const int *time, const int *var, const float *data)
- {
- return v5dWrite(*time, *var, data);
- }
- /*
- * Specify the McIDAS GR3D file number and grid number which correspond
- * to the grid specified by time and var.
- * Input: time, var - timestep and variable of grid (starting at 1)
- * mcfile, mcgrid - McIDAS grid file number and grid number
- * Return: 1 = ok, 0 = errror (bad time or var)
- */
- #ifdef UNDERSCORE
- int v5dmcfile_
- #else
- # ifdef _CRAY
- int V5DMCFILE
- # else
- int v5dmcfile
- # endif
- #endif
- (const int *time, const int *var, const int *mcfile, const int *mcgrid)
- {
- if (*time < 1 || *time > Simple->NumTimes) {
- printf("Bad time argument to v5dSetMcIDASgrid: %d\n", *time);
- return 0;
- }
- if (*var < 1 || *var > Simple->NumVars) {
- printf("Bad var argument to v5dSetMcIDASgrid: %d\n", *var);
- return 0;
- }
- Simple->McFile[*time - 1][*var - 1] = (short)*mcfile;
- Simple->McGrid[*time - 1][*var - 1] = (short)*mcgrid;
- return 1;
- }
- /*
- * Close a simple v5d file.
- */
- #ifdef UNDERSCORE
- int v5dclose_(void)
- #else
- # ifdef _CRAY
- int V5DCLOSE(void)
- # else
- int v5dclose(void)
- # endif
- #endif
- {
- return v5dClose();
- }
|