[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