[ncl-talk] functions handling input of unknown dimension
Walter Kolczynski
walter.kolczynski at noaa.gov
Tue Jun 2 11:09:39 MDT 2015
Will,
Depending on what you are doing, you might be able to flatten into a
lower dimensional array, do whatever operation, then convert back. I've
attached an example to get you started: it returns a random sample in
the left-most dimension of any 2+ dimensional array. To run it just go
into an interactive NCL session, load the file, and run the test procedure:
[user at machine ~]$ ncl
Copyright (C) 1995-2014 - All Rights Reserved
University Corporation for Atmospheric Research
NCAR Command Language Version 6.2.0
The use of this software is governed by a License Agreement.
See http://www.ncl.ucar.edu/ for more details.
ncl 0> load "takeSample.ncl"
ncl 1> test_takeSample()
- Walter
On 02-Jun-15 02:43, Will Hobbs wrote:
> Hi all
>
> I wonder if anyone has any suggestions for a generic way of writing
> functions that deal with input/output arrays which may have different
> numbers of dimensions, e.g.
>
> function generic_example(input:numeric)
>
> begin
> output = some_subset_of_(input)
> return(output)
> end
>
> where input/output might be 1, 2, 3, 4 or more dimensions, and so a
> different line is needed to do the subsetting step.
>
> At the moment I just use nested 'if' statements based on the rank of
> the array (where rank is the number of dimensions, i.e. dimsizes(dim
> sizes(input)), and this works fine. But, it does not make for
> particularly 'clean' or efficient code, so I wonder if anyone has any
> nicer ways of doing this.
>
> Many thanks
>
> Will
>
>
>
> University of Tasmania Electronic Communications Policy (December, 2014).
> This email is confidential, and is for the intended recipient only.
> Access, disclosure, copying, distribution, or reliance on any of it by
> anyone outside the intended recipient organisation is prohibited and
> may be a criminal offence. Please delete if obtained in error and
> email confirmation to the sender. The views expressed in this email
> are not necessarily the views of the University of Tasmania, unless
> clearly intended otherwise.
>
>
>
> _______________________________________________
> ncl-talk mailing list
> ncl-talk at ucar.edu
> List instructions, subscriber options, unsubscribe:
> http://mailman.ucar.edu/mailman/listinfo/ncl-talk
--
Walter Kolczynski, Jr.
Global Ensemble Team
NOAA/NWS/NCEP/EMC (via I.M. Systems Group)
(301) 683-3781
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mailman.ucar.edu/pipermail/ncl-talk/attachments/20150602/a517c420/attachment.html
-------------- next part --------------
; Author: Walter Kolczynski, Jr.
;
; Returns a random sample (with replacement) along the left-most dimension
;
if( isdefined("takeSample") ) then undef("takeSample") end if
function takeSample( \\
data , \\
nSamples : integer \\
)
local dims, nDims, nStates, stateSize, flatData, randomStates, flatSample, newDims, sample, coordNames, dataCoordNames, sampledCoordinate
begin
; detemine data dimensions
dims = dimsizes(data)
nDims = dimsizes(dims) ; total number of dimensions
if( nDims .lt. 2 ) then
print("WARNING (takeSample.ncl::takeSample): Cannot take sample along left-most dimension of a one-dimensional array!")
return( getFillValue(data) )
end if
nStates = dims(0) ; number of states in input
stateSize = product( dims(1:) ) ; size of state vector
flatData = reshape( data, (/nStates,stateSize/) )
; Sample the data
randomStates = floattointeger( floor( random_uniform(0, nStates-1, nSamples) ) ) ; choose random states
flatSample = flatData(randomStates,:)
; Determine the dimension sizes for the new data
newDims = new( nDims, integer )
newDims(0) = nSamples
newDims(1:) = dims(1:)
; Convert flat sample back into correct dimensions
sample = reshape( flatSample, newDims )
; Copy metadata to new array
copy_VarAtts(data, sample)
coordNames = new(nDims, string)
dataCoordNames = getvardims(data)
coordNames(0) = "sample_index"
coordNames(1:) = dataCoordNames(1:)
sample = nameDim( sample, coordNames, "sample of " + data at long_name, data at units )
sample&sample_index = ispan(0, nSamples-1, 1)
do i=1,nDims-1
if ( iscoord( data, coordNames(i) ) ) then sample&$coordNames(i)$ = data&$coordNames(i)$ end if
end do
; If the left-most dimension has a coordinate, save the information on which coordinate was sampled
if( iscoord( data, dataCoordNames(0) ) ) then
sampledCoordinate = data&$dataCoordNames(0)$
sample at sampled_coordinates = sampledCoordinate(randomStates)
end if
return sample
end ; takeSample
;
; test_takeSample
; Tests the function takeSample.
;
if( isdefined("test_takeSample") ) then undef("test_takeSample") end if
procedure test_takeSample()
local a, a_sample, b, b_sample
begin
a = (/ \\
(/ 00, 01, 02 /), \\
(/ 10, 11, 12 /), \\
(/ 20, 21, 22 /), \\
(/ 30, 31, 32 /), \\
(/ 40, 41, 42 /) \\
/)
a!0 = "time"
a!1 = "space"
a&time = ispan( 0, 40, 10 )
a&space = ispan( 0, 2, 1 )
a at long_name = "alpha"
a at units = "angstroms"
a_sample = takeSample( a, 4 )
print(a_sample)
b = (/ \\
(/ \\
(/ 000, 001, 002 /), \\
(/ 010, 011, 012 /) \\
/), (/ \\
(/ 100, 101, 102 /), \\
(/ 110, 111, 112 /) \\
/), (/ \\
(/ 200, 201, 202 /), \\
(/ 210, 211, 212 /) \\
/), (/ \\
(/ 300, 301, 302 /), \\
(/ 310, 311, 312 /) \\
/), (/ \\
(/ 400, 401, 402 /), \\
(/ 410, 411, 412 /) \\
/) \\
/)
b!0 = "time"
b!1 = "space1"
b!2 = "space2"
b&time = ispan( 0, 400, 100 )
b&space1 = ispan( 0, 10, 10 )
b&space2 = ispan( 0, 2, 1)
b at long_name = "beta"
b at units = "bushels"
b_sample = takeSample( b, 4 )
print(b_sample)
return
end ; test_takeSample
More information about the ncl-talk
mailing list