Skip to content

add test program to test attribute copy #45

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#

check_PROGRAMS = tst_atts.py \
tst_copy_attr.py \
tst_default_format.py \
tst_dims.py \
tst_file_fill.py \
Expand Down
9 changes: 8 additions & 1 deletion test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,12 @@ installation information.
+ Test non-blocking APIs and then use `wait/wait_all` method of `File` class
to flush out the pending I/O requests.


* **tst_copy_attr.py**
+ Copying an attribute from one file to another in python can be done without
`ncmpi_copy_att()`. For exampl, this can be done in two lines of python
codes below:
```
att = source_file.get_att("history")
destition_file.put_att('history', att)
```

148 changes: 148 additions & 0 deletions test/tst_copy_attr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#
# Copyright (C) 2024, Northwestern University and Argonne National Laboratory
# See COPYRIGHT notice in top-level directory.
#

"""
This program tests how to copy an attribute from a file to another. Note that
there is no ncmpi_copy_att() function in PnetCDF-Python. This is because
copying a python object is much simpler than in C. In C, without
ncmpi_copy_att(), one have to do the followings.
1. find the size and type of the attribute from the source file
2. malloc space, read from the source file
3. write to the destination file
4. free the buffer

In python, this can be done in two lines of codes:
att = source_file.get_att("history")
destition_file.put_att('history', att)

To run:
% mpiexec -n num_process python3 tst_copy_attr.py [test_file_name]

Example commands for MPI run and outputs from running ncmpidump on the
output netCDF file produced by this example program:

% mpiexec -n num_process python3 tst_copy_attr.py testfile.nc

% ncmpidump testfile.nc
netcdf testfile {
// file format: CDF-1
variables:
int var0 ;
var0:history = "today" ;

// global attributes:
:history = "today" ;
data:

var0 = 0 ;
}
"""

import sys, os, argparse
import numpy as np
from mpi4py import MPI
import pnetcdf


def parse_help():
help_flag = "-h" in sys.argv or "--help" in sys.argv
if help_flag and rank == 0:
help_text = (
"Usage: {} [-h] | [-v] [file_name]\n"
" [-h] Print help\n"
" [-v] Verbose mode\n"
" [-k format] file format: 1 for CDF-1, 2 for CDF-2, 5 for CDF-5\n"
" [filename] (Optional) output netCDF file name\n"
).format(sys.argv[0])
print(help_text)
return help_flag


# Create two files and copy attributes from one file to another
def pnetcdf_io(filename, file_format):

# Create the file
f0 = pnetcdf.File(filename = filename, mode = 'w', format = file_format,
comm = comm, info = None)

filename_dup = filename + "_dup.nc"
f1 = pnetcdf.File(filename = filename_dup, mode = 'w', format = file_format,
comm = comm, info = None)

# define a variable in each file
v0 = f0.def_var('var0', 'i4', ())
v1 = f1.def_var('var1', 'i4', ())

# put a new global attribute in f0
f0.put_att('history','today')

# put a new attribute to variable v0 in f0
v0.put_att('history','today')

# retrieve the global attribute from f0
att = f0.get_att("history")

# copy it to f1
f1.put_att('history', att)

# retrieve v0's attribute from f0
v_att = v0.get_att("history")

# copy it to variable v1 in f1
v1.put_att('history', v_att)

# close files
f0.close()
f1.close()

# Open file f1 and check the attribute contents
f1 = pnetcdf.File(filename_dup, 'r', comm = comm)
assert("today" == f1.get_att("history"))

v1=f1.variables['var1']
assert("today" == v1.get_att("history"))

# close files
f1.close()


if __name__ == "__main__":
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
nprocs = comm.Get_size()

if parse_help():
MPI.Finalize()
sys.exit(1)

# get command-line arguments
args = None
parser = argparse.ArgumentParser()
parser.add_argument("dir", nargs="?", type=str, help="(Optional) output directory name",\
default = ".")
parser.add_argument("-v", help="Verbose mod ", action="store_true")
parser.add_argument("-k", help="File format: 1 for CDF-1, 2 for CDF-2, 5 for CDF-5")
args = parser.parse_args()

verbose = True if args.v else False

file_format = None
if args.k:
kind_dict = {'1':None, '2':"NC_64BIT_OFFSET", '5':"NC_64BIT_DATA"}
file_format = kind_dict[args.k]

filename = os.path.join(args.dir, "tst_copy_attr.nc")

if verbose and rank == 0:
print("{}: test copying attributes ".format(os.path.basename(__file__)))

try:
pnetcdf_io(filename, file_format)
except BaseException as err:
print("Error: type:", type(err), str(err))
raise

MPI.Finalize()

Loading