Skip to content

Commit 01c5343

Browse files
committed
added support for using non-standard locations for hdfeos library, closes quintusdias#43
Had to use "modulename" option to cffi verifier to keep cffi from recompiling the module after it's been installed.
1 parent c76b82e commit 01c5343

File tree

7 files changed

+226
-190
lines changed

7 files changed

+226
-190
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
*.pyc
2+
*.so

README.md

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,28 @@ packages include
2121
* numpy
2222
* numpy-devel
2323

24-
Both HDF-EOS and HDF-EOS5 are required. On some systems, such as Linux Mint,
25-
this is pretty easy, just make sure you have the devel packages installed as
26-
well.
24+
Both the HDF-EOS and HDF-EOS5 libraries are required. On some
25+
systems, such as Linux Mint, these are readily available through
26+
the system package manager, just make sure you have the devel
27+
packages installed as well. On such a system, the install command is just::
28+
29+
python setup.py install --user
2730

2831
Other systems such as OpenSUSE do not provide packages for HDF-EOS or HDF-EOS5,
29-
so they must be compiled from source. You should install the libraries (and
30-
the header files) into ```/usr/local```. Be advised, however, that there is
31-
a bug with HDF-EOS version 1.15 that prevents it from being used as-is with
32-
```pyhdfeos```. You can patch it by editing ```src/EHapi.c``` and delete line
33-
11545.
32+
so they must be compiled from source.
33+
34+
Be advised, however, that there is a bug with HDF-EOS version 1.15
35+
that prevents it from being used as-is with ```pyhdfeos```. You
36+
can patch it by editing ```src/EHapi.c``` and delete line 11545.
37+
38+
Ideally, you would install the libraries and header files into
39+
```/usr/local```, but if that is not possible, you would need to
40+
augment the search path when installing pyhdfeos with ```INCLUDE_DIRS```
41+
and ```LIBRARY_DIRS``` environment variables, something like
42+
43+
export INCLUDE_DIRS=/path/to/hdfeos/include
44+
export LIBRARY_DIRS=/path/to/hdfeos/lib
45+
python setup.py install --user
3446

3547
Macports provides packages for both HDF-EOS and HDF-EOS5, but the HDF-EOS5 port
3648
has the bug described above, so you should compile HDF-EOS5 from source.

pyhdfeos/lib/config.py

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import binascii
12
import os
23

34
# HDFEOS relies on GCTP, but sometimes this library is called "Gctp" and
@@ -20,7 +21,7 @@ def locate_gctp(library_dirs):
2021

2122
if true_gctp_lib is None:
2223
msg = "Could not locate gctp library. Please specify a location with "
23-
msg += "the LIBRARY_DIRS environment variable as specified in README.md."
24+
msg += "the HDFEOS_ROOT environment variable as specified in README.md."
2425
raise RuntimeError(msg)
2526
return None
2627

@@ -35,33 +36,42 @@ def library_config(libraries):
3536
"""
3637
global library_dir_candidates
3738
library_dirs = []
38-
libraries = []
3939

4040
# On Fedora, gctp is named libGctp, but on ubuntu variants, it is libgctp.
4141
suffix_list = ['a', 'so', 'dylib', 'dll']
4242
for libname in libraries:
4343
for library_dir in library_dir_candidates:
4444
for suffix in suffix_list:
4545
path = os.path.join(library_dir, 'lib' + libname + '.' + suffix)
46-
#print(path)
4746
if os.path.exists(path):
4847
if library_dir not in library_dirs:
4948
library_dirs.append(library_dir)
5049

5150
return library_dirs
5251

5352
# Locations where we might look for HDF, HDF-EOS, and HDF-EOS5 libraries.
54-
# Modify this for your local configuration.
5553
include_dirs=['/usr/include/hdf',
5654
'/usr/include/x86_64-linux-gnu/hdf',
5755
'/usr/include/i386-linux-gnu/hdf',
5856
'/opt/local/include',
5957
'/usr/local/include',
6058
'/usr/include/hdf-eos5']
59+
if 'INCLUDE_DIRS' in os.environ:
60+
lst = os.environ['INCLUDE_DIRS'].split(':')
61+
lst.extend(include_dirs)
62+
include_dirs = lst
6163

62-
library_dir_candidates = ['/usr/lib', '/usr/lib/hdf', '/usr/lib64/hdf',
63-
'/usr/lib/i386-linux-gnu', '/usr/lib/x86_64-linux-gnu',
64-
'/usr/local/lib', '/opt/local/lib']
64+
library_dir_candidates = ['/usr/lib',
65+
'/usr/lib/hdf',
66+
'/usr/lib64/hdf',
67+
'/usr/lib/i386-linux-gnu',
68+
'/usr/lib/x86_64-linux-gnu',
69+
'/usr/local/lib',
70+
'/opt/local/lib']
71+
if 'LIBRARY_DIRS' in os.environ:
72+
lst = os.environ['LIBRARY_DIRS'].split(':')
73+
lst.extend(library_dir_candidates)
74+
library_dir_candidates = lst
6575

6676
hdf4_libs = ['mfhdf', 'df', 'jpeg', 'z']
6777

@@ -70,3 +80,19 @@ def library_config(libraries):
7080

7181
hdfeos5_libs = ['he5_hdfeos', true_gctp_lib]
7282
hdfeos5_libs.extend(['hdf5_hl', 'hdf5', 'z'])
83+
84+
def _create_modulename(tag, cdef_sources, source, sys_version):
85+
"""
86+
This is the same as CFFI's create modulename except we don't include the
87+
CFFI version.
88+
89+
See https://caremad.io/2014/11/distributing-a-cffi-project/
90+
"""
91+
key = '\x00'.join([sys_version[:3], source, cdef_sources])
92+
key = key.encode('utf-8')
93+
k1 = hex(binascii.crc32(key[0::2]) & 0xffffffff)
94+
k1 = k1.lstrip('0x').rstrip('L')
95+
k2 = hex(binascii.crc32(key[1::2]) & 0xffffffff)
96+
k2 = k2.lstrip('0').rstrip('L')
97+
return '_{0}_cffi_{1}{2}'.format(tag,k1, k2)
98+

pyhdfeos/lib/hdf.py

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Interface for HDF4 library. Need this in order to access HDF-EOS2 field
33
attributes.
44
"""
5+
import sys
6+
57
import numpy as np
68
from cffi import FFI
79

@@ -22,46 +24,53 @@
2224
DFTAG_NDG = 720
2325
DFTAG_VG = 1965
2426

27+
CDEF = """
28+
typedef short int int16;
29+
typedef unsigned short int uint16;
30+
typedef int int32;
31+
typedef int intn;
32+
int32 Hopen(const char *path, intn acc_mode, int16 ndds);
33+
intn Hclose(int32 file_id);
34+
intn SDattrinfo(int obj_id, int32 idx, char *name, int32 *dtype,
35+
int32 *count);
36+
intn SDendaccess(int32 sds_id);
37+
intn SDgetinfo(int32 sdsid, char *name, int32 *rank,
38+
int32 dimsizes[], int32 *datatype, int32 *nattrs);
39+
int32 SDnametoindex(int32 sdid, char *sds_name);
40+
int32 SDreftoindex(int32 sd_id, int32 sds_ref);
41+
int32 SDselect(int32 sdid, int32 idx);
42+
intn SDreadattr(int32 obj_id, int32 idx, void *buffer);
43+
intn SDend(int32 fid);
44+
int32 SDstart(char *filename, int32 access_mode);
45+
int32 Vattach(int32 fid, int32 vgroup_ref, char *access);
46+
int32 Vdetach(int32 vgroup_id);
47+
intn Vend(int32 fid);
48+
int32 Vfind(int32 fid, char *vgroup_name);
49+
int32 Vgetname(int32 vgroup_id, char *vgroup_name);
50+
int32 Vgetnamelen(int32 vgroup_id, uint16 *namelen);
51+
int32 Vgettagrefs(int32 vgroup_id, int32 tags[], int32 refs[],
52+
int32 npairs);
53+
int32 Vntagrefs(int32 vgroup_id);
54+
intn Vstart(int32 fid);
55+
"""
56+
57+
SOURCE = """
58+
#include "hdf.h"
59+
#include "mfhdf.h"
60+
"""
61+
2562
ffi = FFI()
26-
ffi.cdef("""
27-
typedef short int int16;
28-
typedef unsigned short int uint16;
29-
typedef int int32;
30-
typedef int intn;
31-
int32 Hopen(const char *path, intn acc_mode, int16 ndds);
32-
intn Hclose(int32 file_id);
33-
intn SDattrinfo(int obj_id, int32 idx, char *name, int32 *dtype,
34-
int32 *count);
35-
intn SDendaccess(int32 sds_id);
36-
intn SDgetinfo(int32 sdsid, char *name, int32 *rank,
37-
int32 dimsizes[], int32 *datatype, int32 *nattrs);
38-
int32 SDnametoindex(int32 sdid, char *sds_name);
39-
int32 SDreftoindex(int32 sd_id, int32 sds_ref);
40-
int32 SDselect(int32 sdid, int32 idx);
41-
intn SDreadattr(int32 obj_id, int32 idx, void *buffer);
42-
intn SDend(int32 fid);
43-
int32 SDstart(char *filename, int32 access_mode);
44-
int32 Vattach(int32 fid, int32 vgroup_ref, char *access);
45-
int32 Vdetach(int32 vgroup_id);
46-
intn Vend(int32 fid);
47-
int32 Vfind(int32 fid, char *vgroup_name);
48-
int32 Vgetname(int32 vgroup_id, char *vgroup_name);
49-
int32 Vgetnamelen(int32 vgroup_id, uint16 *namelen);
50-
int32 Vgettagrefs(int32 vgroup_id, int32 tags[], int32 refs[],
51-
int32 npairs);
52-
int32 Vntagrefs(int32 vgroup_id);
53-
intn Vstart(int32 fid);
54-
"""
55-
)
63+
ffi.cdef(CDEF)
5664

5765
libraries = config.hdf4_libs
58-
_lib = ffi.verify("""
59-
#include "hdf.h"
60-
#include "mfhdf.h"
61-
""",
62-
libraries=libraries,
63-
include_dirs=config.include_dirs,
64-
library_dirs=config.library_config(libraries))
66+
_lib = ffi.verify(SOURCE,
67+
libraries=libraries,
68+
include_dirs=config.include_dirs,
69+
library_dirs=config.library_config(libraries),
70+
modulename=config._create_modulename("_hdf4",
71+
CDEF,
72+
SOURCE,
73+
sys.version))
6574

6675

6776
def _handle_error(status):

pyhdfeos/lib/he4.py

Lines changed: 54 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7,60 +7,66 @@
77

88
from . import config
99

10+
CDEF = """
11+
typedef float float32;
12+
typedef int int32;
13+
typedef int intn;
14+
typedef double float64;
15+
16+
intn EHidinfo(int32 fid, int32 *hdfid, int32 *sdid);
17+
int32 GDattach(int32 gdfid, char *grid);
18+
intn GDattrinfo(int32 gdfid, char *attrname, int32 *nbyte, int32
19+
*count);
20+
intn GDblkSOMoffset(int32 fid, float32 [], int32 count, char *code);
21+
intn GDdetach(int32 gid);
22+
intn GDclose(int32 fid);
23+
intn GDfieldinfo(int32 gridid, char *fieldname, int32 *rank,
24+
int32 dims[], int32 *numbertype, char *dimlist);
25+
int32 GDij2ll(int32 projcode, int32 zonecode,
26+
float64 projparm[], int32 spherecode, int32 xdimsize,
27+
int32 ydimsize, float64 upleft[], float64 lowright[],
28+
int32 npts, int32 row[], int32 col[], float64
29+
longititude[], float64 latitude[], int32 pixcen,
30+
int32 pixcnr);
31+
int32 GDinqattrs(int32 gridid, char *attrlist, int32 *strbufsize);
32+
int32 GDinqdims(int32 gridid, char *dimname, int32 *dims);
33+
int32 GDinqfields(int32 gridid, char *fieldlist, int32 rank[],
34+
int32 numbertype[]);
35+
int32 GDinqgrid(char *filename, char *gridlist, int32 *strbufsize);
36+
int32 GDnentries(int32 gridid, int32 entrycode, int32 *strbufsize);
37+
intn GDgridinfo(int32 gridid, int32 *xdimsize, int32 *ydimsize,
38+
float64 upleft[2], float64 lowright[2]);
39+
int32 GDopen(char *name, intn access);
40+
intn GDorigininfo(int32 gridid, int32 *origincode);
41+
intn GDpixreginfo(int32 gridid, int32 *pixregcode);
42+
intn GDprojinfo(int32 gridid, int32 *projcode, int32 *zonecode,
43+
int32 *spherecode, float64 projparm[]);
44+
intn GDreadattr(int32 gridid, char* attrname, void *buffer);
45+
intn GDreadfield(int32 gridid, char* fieldname, int32 start[],
46+
int32 stride[], int32 edge[], void *buffer);
47+
"""
48+
49+
SOURCE = """
50+
#include "mfhdf.h"
51+
#include "HdfEosDef.h"
52+
"""
53+
1054
ffi = FFI()
11-
ffi.cdef("""
12-
typedef float float32;
13-
typedef int int32;
14-
typedef int intn;
15-
typedef double float64;
16-
17-
intn EHidinfo(int32 fid, int32 *hdfid, int32 *sdid);
18-
int32 GDattach(int32 gdfid, char *grid);
19-
intn GDattrinfo(int32 gdfid, char *attrname, int32 *nbyte, int32
20-
*count);
21-
intn GDblkSOMoffset(int32 fid, float32 [], int32 count, char *code);
22-
intn GDdetach(int32 gid);
23-
intn GDclose(int32 fid);
24-
intn GDfieldinfo(int32 gridid, char *fieldname, int32 *rank,
25-
int32 dims[], int32 *numbertype, char *dimlist);
26-
int32 GDij2ll(int32 projcode, int32 zonecode,
27-
float64 projparm[], int32 spherecode, int32 xdimsize,
28-
int32 ydimsize, float64 upleft[], float64 lowright[],
29-
int32 npts, int32 row[], int32 col[], float64
30-
longititude[], float64 latitude[], int32 pixcen,
31-
int32 pixcnr);
32-
int32 GDinqattrs(int32 gridid, char *attrlist, int32 *strbufsize);
33-
int32 GDinqdims(int32 gridid, char *dimname, int32 *dims);
34-
int32 GDinqfields(int32 gridid, char *fieldlist, int32 rank[],
35-
int32 numbertype[]);
36-
int32 GDinqgrid(char *filename, char *gridlist, int32 *strbufsize);
37-
int32 GDnentries(int32 gridid, int32 entrycode, int32 *strbufsize);
38-
intn GDgridinfo(int32 gridid, int32 *xdimsize, int32 *ydimsize,
39-
float64 upleft[2], float64 lowright[2]);
40-
int32 GDopen(char *name, intn access);
41-
intn GDorigininfo(int32 gridid, int32 *origincode);
42-
intn GDpixreginfo(int32 gridid, int32 *pixregcode);
43-
intn GDprojinfo(int32 gridid, int32 *projcode, int32 *zonecode,
44-
int32 *spherecode, float64 projparm[]);
45-
intn GDreadattr(int32 gridid, char* attrname, void *buffer);
46-
intn GDreadfield(int32 gridid, char* fieldname, int32 start[],
47-
int32 stride[], int32 edge[], void *buffer);
48-
"""
49-
)
55+
ffi.cdef(CDEF)
5056

5157
libraries = config.hdfeos_libs
5258
libraries.extend(config.hdf4_libs)
5359
library_dirs = config.library_config(libraries)
5460

55-
_lib = ffi.verify("""
56-
#include "mfhdf.h"
57-
#include "HE2_config.h"
58-
#include "HdfEosDef.h"
59-
""",
60-
ext_package='pyhdfeos',
61-
libraries=libraries,
62-
include_dirs=config.include_dirs,
63-
library_dirs=library_dirs)
61+
_lib = ffi.verify(SOURCE,
62+
ext_package='pyhdfeos',
63+
libraries=libraries,
64+
include_dirs=config.include_dirs,
65+
library_dirs=library_dirs,
66+
modulename=config._create_modulename("_hdfeos",
67+
CDEF,
68+
SOURCE,
69+
sys.version))
6470

6571
def _handle_error(status):
6672
if status < 0:

0 commit comments

Comments
 (0)