Changeset 3351


Ignore:
Timestamp:
10/02/08 07:54:08 (12 years ago)
Author:
astephen
Message:
 
Location:
nappy/trunk/nappy
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • nappy/trunk/nappy/Plans for re-factoring 2008.txt

    r3350 r3351  
    3434    * FFI 2110 is best for 2D columns for Excel etc. - Nappy must support this  
    3535 
     36---------------------- 
     37 
     38 
     39=== Adding annotation column === 
     40 
     41via argument: annotated=True|False 
     42 
     43Only on output. So only affects write methods.  
     44NOTE: could do read as well by reading in file and then removing column 1 (as long as we know the delimiter is a comma). But don't do this now. 
     45 
     46Ask Charles to come up with a list of definitions for each column in a config file. 
     47 
     48Need to defined names in config file and a ways of mapping to each of the lines by tagging to self.A, self.X self.XNAMES etc 
     49 
     50=== Adding CSV === 
     51 
     52Via delimiter/spacer argument. Would be nice to have a writeCSV() method. 
     53 
     54Should 'csv' and 'delim' args be sent to write methods rather than __init__()? 
     55--- 
     56 
     57=== 
     58 
     59Do we need global DEBUG = True|False 
     60 
     61Then all the prints could be: 
     62 
     63if DEBUG == True: print "blah" 
    3664 
    3765=============== 
  • nappy/trunk/nappy/bin/na2nc.py

    r3324 r3351  
    118118    convertor = apply(nappy.nc_convertor.na_to_nc.NAToNC, [], arg_dict) 
    119119    convertor.convert() 
    120     convertor.writeFile(nc_file, mode)     
     120    convertor.write(nc_file, mode)     
    121121 
    122122 
  • nappy/trunk/nappy/cdms_utils/axis_utils.py

    r3331 r3351  
    2020import cdms 
    2121 
    22 def compareAxes(ax1, ax2): 
     22def areAxesIdentical(ax1, ax2): 
    2323    """ 
    24     Takes 2 cmds axis objects returning 1 if they are essentially 
    25     the same and 0 if not. 
     24    Takes 2 CDMS axis objects returning True if they are essentially 
     25    the same and False if not. 
    2626    """ 
    2727    for axtype in ("time", "level", "latitude", "longitude"): 
    2828        if cdms.axisMatches(ax1, axtype) and not cdms.axisMatches(ax2, axtype): 
    29             return 0 
     29            return False 
    3030 
    3131    # Check ids 
    32     if ax1.id != ax2.id: return 0 
     32    if ax1.id != ax2.id: return False 
    3333    # Check lengths 
    34     if len(ax1) != len(ax2): return 0 
     34    if len(ax1) != len(ax2): return False 
    3535    # Check values 
    36     if ax1._data_ != ax2._data_: return 0 
     36    if ax1._data_ != ax2._data_: return False 
    3737    # Check units 
    38     if ax1.units != ax2.units: return 0 
     38    if ax1.units != ax2.units: return False 
    3939    # OK, I think they are the same axis! 
    40     return 1 
     40    return True 
    4141 
  • nappy/trunk/nappy/cdms_utils/var_utils.py

    r3331 r3351  
    1919# Import external packages 
    2020import cdms 
    21  
    2221cdms.setAutoBounds("off")  
    2322 
     23# Import local modules 
     24import nappy.cdms_utils.axis_utils 
    2425 
    2526def compareVariables(var1, var2): 
     
    3233            ax1 = var1.getAxis(i) 
    3334            ax2 = var2.getAxis(i)         
    34             if compareAxes(ax1, ax2) == 0: 
     35            if nappy.cdms_utils.axis_utils.areAxesIdentical(ax1, ax2) == True: 
    3536                return 0 
    3637    except: 
  • nappy/trunk/nappy/nc_interface/cdms_to_na.py

    r3349 r3351  
    2525import nappy.na_file.na_core 
    2626 
    27 nc_to_na_map = utils.getConfigDict()["nc_to_na_map"] 
    2827 
    2928# Import external packages (if available) 
     
    4342 
    4443 
    45  
    46 def cdms2na(ncfile, na_file_names, na_vars={}, variables=None, only_return_file_names="no",  
    47             ffi="automatic", spacer="    ", float_format="%g", size_limit=None): 
     44class NCToNA: 
    4845    """ 
     46    Converts a NetCDF file to one or more NASA Ames files. 
     47    """ 
     48 
     49    def __init__(self, nc_file, na_file_names=None, na_vars={}, variables=None,  
     50            only_return_file_names="no", spacer="    ", float_format="%g",  
     51            size_limit=None): 
     52 
     53 
     54        """ 
     55        Sets up instance variables. Note that the argument 'na_file' has a relaxes definition 
     56        and can be either a NASA Ames file object or the name of a NASA AMES file. 
     57        Typical usage is: 
     58        >>>    import nappy.nc_interface.nc_to_na as nc_to_na 
     59        >>>    c = nc_to_na("old_file.nc")  
     60        >>>    c.convert() 
     61        >>>    c.write("new_file.na")          
     62        """ 
     63 
     64 
     65 
     66 
     67 
     68 
     69 
     70 
     71 
     72 
     73 
     74 
     75 
     76        """ 
     77        Set up instance variables, and call 
    4978    Main conversion function that calls the appropriate classes and functions 
    5079    to write a NASA Ames file. 
     
    73102        # Deal with singleton variables 
    74103        if not hasattr(var_obj, "rank"): 
    75                 varMetadata = cdms_file[variable].attributes 
    76                 varValue = var_obj 
    77                 var_obj = cdms.createVariable(Numeric.array(var_obj), id=nappy.cdms_utils.var_utils.getBestName(varMetadata).replace(" ", "_"), attributes=varMetadata) 
     104                var_metadata = cdms_file[variable].attributes 
     105                var_value = var_obj 
     106                var_obj = cdms.createVariable(Numeric.array(var_obj),  
     107                    id=nappy.cdms_utils.var_utils.getBestName(var_metadata).replace(" ", "_"),  
     108                    attributes=var_metadata) 
    78109                var_obj.value = var_obj._data[0]                  
    79110        vars.append(var_obj) 
     
    83114    other_vars = [] 
    84115    for var in vars: 
    85         varMetadata = cdms_file[var] 
    86         if hasattr(varMetadata, "nasa_ames_var_number"): 
    87             num = varMetadata.nasa_ames_var_number 
     116        var_metadata = cdms_file[var] 
     117        if hasattr(var_metadata, "nasa_ames_var_number"): 
     118            num = var_metadata.nasa_ames_var_number 
    88119            ordered_vars[num] = var 
    89120        else: 
     
    97128    vars = vars + other_vars 
    98129     
    99     builder = NAContentCollector(vars, globals, rule=rule, cdms_file=cdms_file) 
     130    builder = NAContentCollector(vars, globals) 
     131 
     132                collectNAContent 
     133 
     134 
    100135    built_na_dicts = [[builder.na_dict, builder.var_ids]] 
    101136 
     
    106141        return output_message 
    107142 
    108     while len(builder.varBin) > 0: 
    109         builder = NAContentCollector(builder.varBin, globals, rule=rule, cdms_file=cdms_file) 
     143    while len(builder.unused_vars) > 0: 
     144        builder = NAContentCollector(builder.unused_vars, globals) 
     145 
     146              collectNAContent 
     147 
    110148        output_message = output_message + builder.output_message 
    111149        if builder.var_ids != None:  built_na_dicts.append([builder.na_dict, builder.var_ids]) 
  • nappy/trunk/nappy/nc_interface/na_content_collector.py

    r3349 r3351  
    3838cdms.setAutoBounds("off")  
    3939 
    40 class CdmsToNABuilder --> NAContentCollector: (na_dict, var_ids, varBin) 
    41 __init__ --> sets everything up and runs it move some to --> analyse() 
    42 analyseVariables 
    43 defineNAVars 
    44 defineNAAuxVars 
    45 getAxisDefinition 
    46 defineNAGlobals 
    47 defineNAComments 
    48 defineGeneralHeader 
    49  
    50  
    5140 
    5241class NAContentCollector(NACore): 
     
    5645    """ 
    5746     
    58     def __init__(self, vars, global_attributes={}, cdms_file=None): 
     47    def __init__(self, variables, global_attributes={}): 
    5948        """ 
    6049        Sets up instance variables and calls appropriate methods to 
    6150        generate sections of NASA Ames file object. 
    62         """ 
    63         self.cdms_file = cdms_file 
     51 
     52        Input arguments are: 
     53          * variables - list/tuple of actual CDMS variables 
     54          * global_attributes - dictionary of user-defined globals to include. 
     55 
     56        Typical usage: 
     57        >>> x = NAContentCollector(["temp", "precip"]) 
     58        >>> x.collectNAContent() 
     59        >>> print x.na_dict, x.var_ids, x.unused_vars  
     60        """ 
    6461        self.output_message = [] 
    6562        self.na_dict = {} 
    66         self.vars = vars 
     63        self.vars = variables 
     64 
     65        # Note that self.var_ids will be a list containing: 
     66        #    [ordered_vars,  auxiliary_vars,   rank_zero_vars] 
    6767        self.var_ids = None 
    6868        self.globals = global_attributes         
    6969        self.rank_zero_vars = [] 
    7070        self.rank_zero_var_ids = [] 
    71         (self.ordered_vars, aux_vars) = self.analyseVariables() 
     71 
     72 
     73    def collectNAContent(self): 
     74        """ 
     75        Collect NASA Ames content. Save the contents to the following instance 
     76        attributes: 
     77         * self.na_dict 
     78         * self.var_ids 
     79         * self.unused_vars 
     80        """ 
     81        (self.ordered_vars, aux_vars) = self._analyseVariables() 
    7282        if self.ordered_vars == None: 
    73             self.var_bin = [] 
     83            self.unused_vars = [] 
    7484        else: 
    75  
    76             self.var_ids = [[var.id for var in self.ordered_vars],[var.id for var in aux_vars], self.rank_zero_var_ids] 
    77          
     85            self.var_ids = [[var.id for var in self.ordered_vars], 
     86                            [var.id for var in aux_vars],  
     87                            self.rank_zero_var_ids] 
    7888            self.na_dict["NLHEAD"] = "-999" 
    79          
    80             #print [var.id for var in self.ordered_vars] 
    81             #print [var.rank() for var in self.ordered_vars]     
    82             self.defineNAVars(self.ordered_vars) 
    83             self.defineNAAuxVars(aux_vars) 
    84             self.defineNAGlobals() 
    85             self.defineNAComments() 
    86             self.defineGeneralHeader() 
    87             # Quick fudge 
    88             if self.na_dict["FFI"] == 1001: self.na_dict["X"] = self.na_dict["X"][0] 
    89  
     89            self._defineNAVars(self.ordered_vars) 
     90            self._defineNAaux_vars(aux_vars) 
     91            self._defineNAGlobals() 
     92            self._defineNAComments() 
     93            self._defineGeneralHeader() 
     94            # Quick fudge to cope with 1001 issue 
     95            if self.na_dict["FFI"] == 1001:  
     96                self.na_dict["X"] = self.na_dict["X"][0] 
    9097 
    9198    def analyseVariables(self): 
     
    94101        a tuple of two lists containing variables and auxiliary variables 
    95102        for the NASA Ames file object. 
    96         Variables not compatible with the first file are binned to be used next. 
    97         """ 
    98         # Need to group the variables together in bins 
    99         self.var_bin = [] 
    100         # Get largest ranked variable as the one we use as standard 
    101         highrank = -1 
     103        Variables not compatible with the first file are put in self.unused_vars 
     104        """ 
     105        self.unused_vars = [] 
     106 
     107        highest_rank = -1 
    102108        best_var = None 
    103109        count = 0 
     110 
     111        # Need to get highest ranked variable (most dimensions) so that we can work out FFI 
    104112        for var in self.vars: 
    105113            msg = "Analysing: %s" % var.id 
     
    107115            self.output_message.append(msg) 
    108116            count = count + 1 
    109  
    110117            # get rank 
    111118            rank = var.rank() 
    112119 
    113120            # Deal with singleton variables 
    114             if rank == 0:  
    115                 self.rank_zero_vars.append(var) 
    116                 self.rank_zero_var_ids.append(var.id) 
    117                 continue 
     121            if rank == 0:  
     122                self.rank_zero_vars.append(var) 
     123                self.rank_zero_var_ids.append(var.id) 
     124                continue 
    118125             
    119             if rank > highrank: 
    120                 highrank = rank 
    121                 best_var = var 
    122                 best_var_index = count 
    123             elif rank == highrank: 
    124                 if len(var.flat) > len(best_var.flat): 
    125                     best_var = var 
    126                     best_var_index = count 
    127          
    128         if len(self.rank_zero_vars) == len(self.vars):  return (None, None) 
    129         if not best_var:   
    130             print "No variables produced" 
     126            # Update highest if highest found or if equals highest with bigger size 
     127            if rank > highest_rank or (rank == highest_rank and var.size() > best_var.size()): 
     128                highest_rank = rank 
     129                best_var = var 
     130                best_var_index = count 
     131                print "WARNING WARNING WARNING....CHANGED CODE HERE from len(var.flat) to var.size() which should be quicker!!!" 
     132 
     133        # If all are zero ranked variables or no vars identified/found then we cannot write any to NASA Ames and return (None, None) 
     134        if len(self.rank_zero_vars) == len(self.vars) or best_var == None:  
     135            print "No usable variables found."  
    131136            return (None, None) 
    132137 
     138        # Now start to sort the variables into main and auxiliary  
    133139        vars_for_na = [best_var] 
    134140        aux_vars_for_na = [] 
    135141        shape = best_var.shape 
    136         ndims = len(shape) 
    137         self.na_dict["NIV"] = ndims 
    138  
    139         # Work out which File Format Index is appropriate  
    140         if ndims in (2,3,4): 
    141             self.na_dict["FFI"] = 10 + (ndims * 1000) 
    142         elif ndims > 4: 
    143             raise "Cannot write variables defined against greater than 4 axes in NASA Ames format." 
     142        number_of_dims = len(shape) 
     143        self.na_dict["NIV"] = number_of_dims 
     144        # Get the FFI 
     145        self.na_dict["FFI"] = self._decideFileFormatIndex(number_of_dims) 
     146        # Get the axes for the main variable being used 
     147        best_var_axes = best_var.getAxisList() 
     148         
     149        # Get other variable info 
     150        rest_of_the_vars = self.vars[:best_var_index - 1] + self.vars[best_var_index:] 
     151 
     152        for var in rest_of_the_vars: 
     153 
     154            if var.id in self.rank_zero_var_ids: continue 
     155 
     156            # What to do with variables that have different number of dimensions or different shape 
     157            if len(var.shape) != number_of_dims or var.shape != shape:  
     158                # Could it be an auxiliary variable? 
     159                if len(var.shape) != 1:  
     160                    self.unused_vars.append(var) 
     161                    continue 
     162 
     163                first_axis = var.getAxis(0) 
     164 
     165                if nappy.cdms_utils.axis_utils.areAxesIdentical(best_var_axes[0], first_axis) == False:  
     166                    self.unused_vars.append(var) 
     167                    continue 
     168 
     169                # I think it is an auxiliary variable 
     170                aux_vars_for_na.append(var)  
     171                # Also put it in unused var bin because auxiliary vars might be useful later on in there own right 
     172                self.unused_vars.append(var) 
     173            else: 
     174                this_var_axes = var.getAxisList() 
     175 
     176                # Loop through dimensions 
     177                for i in range(number_of_dims):             
     178                    if nappy.cdms_utils.axis_utils.areAxesIdentical(best_var_axes[i], this_var_axes[i]) == False: 
     179                        self.unused_vars.append(var) 
     180                        continue 
     181 
     182                # OK, I think the current variable is compatible to write with the best variable along with a NASA Ames file  
     183                vars_for_na.append(var) 
     184                 
     185        # Send vars_for_na AND aux_vars_for_na to a method to check if they have previously been mapped  
     186        # from NASA Ames. In which case we'll write them back in the order they were initially read from the input file. 
     187        (vars_for_na, aux_vars_for_na) = self._reorderVarsIfPreviouslyNA(vars_for_na, aux_vars_for_na) 
     188        return (vars_for_na, aux_vars_for_na) 
     189 
     190 
     191    def _reorderVarsIfPreviouslyNA(vars_for_na, aux_vars_for_na): 
     192        """ 
     193        Re-order if they previously came from NASA Ames files (i.e. including the  
     194        attribute 'nasa_ames_var_number'). Return re-ordered or unchanged pair of 
     195        (vars_for_na, aux_vars_for_na). 
     196        """ 
     197        # THIS SHOULD REALLY BE DONE IN A LOOP 
     198        # First do the main variables 
     199        ordered_vars = [None] * 1000 # Make a long list to put vars in  
     200        # Create a list of other variables to collect up any that are not labelled as nasa ames variables 
     201        other_vars = [] 
     202        for var in vars_for_na: 
     203            if hasattr(var, "nasa_ames_var_number"): 
     204                ordered_vars[var.nasa_ames_var_number[0]] = var 
     205            else: 
     206                other_vars.append(var) 
     207 
     208        # Remake vars_for_na now in new order and clean out any that are "None" 
     209        vars_for_na = [] 
     210        for var in ordered_vars: 
     211            if var != None:  
     212                vars_for_na.append(var) 
     213 
     214        vars_for_na = vars_for_na + other_vars 
     215 
     216        # Now re-order the Auxiliary variables if they previously came from NASA  
     217        ordered_aux_vars = [None] * 1000 
     218        other_aux_vars = [] 
     219 
     220        for var in aux_vars_for_na: 
     221            if hasattr(var, "nasa_ames_aux_var_number"): 
     222                ordered_aux_vars[var.nasa_ames_aux_var_number[0]] = var 
     223            else: 
     224                other_aux_vars.append(var) 
     225 
     226        # Remake aux_vars_for_na now in order 
     227        aux_vars_for_na = [] 
     228        for var in ordered_aux_vars: 
     229            if var != None:  
     230                aux_vars_for_na.append(var) 
     231 
     232        aux_vars_for_na = aux_vars_for_na + other_aux_vars       
     233        return (vars_for_na, aux_vars_for_na) 
     234 
     235 
     236    def _decideFileFormatIndex(self, number_of_dims): 
     237        """ 
     238        Based on the number of dimensions and the NASA Ames dictionary return 
     239        the File Format Index. 
     240        """ 
     241        if number_of_dims in (2,3,4): 
     242            ffi = 10 + (number_of_dims * 1000) 
     243        elif number_of_dims > 4: 
     244            raise Exception("Cannot write variables defined against greater than 4 axes in NASA Ames format.") 
    144245        else: 
    145246            if len(aux_vars_for_na) > 0 or (self.na_dict.has_key("NAUXV") and self.na_dict["NAUXV"] > 0): 
    146                 self.na_dict["FFI"] = 1010 
     247                ffi = 1010 
    147248            else: 
    148                 self.na_dict["FFI"] = 1001 
    149  
    150         axes = best_var.getAxisList() 
    151          
    152         # Get other variable info 
    153         for var in self.vars[:best_var_index - 1] + self.vars[best_var_index:]: 
    154  
    155             if var.id in self.rank_zero_var_ids: continue 
    156             if len(var.shape) != ndims or var.shape != shape:  
    157                 # Could it be an auxiliary variable  
    158                 if len(var.shape) != 1:  
    159                     self.var_bin.append(var) 
    160                     continue 
    161                 caxis = var.getAxis(0) 
    162                 if nappy.cdms_utils.axis_utils.compareAxes(axes[0], caxis) == 0:  
    163                     self.var_bin.append(var) 
    164                     continue 
    165                 # I think it is an auxiliary variable 
    166                 aux_vars_for_na.append(var)  
    167                 # Also put it in var bin because auxiliary vars might be useful 
    168                 self.var_bin.append(var) 
    169             else: 
    170                 caxes = var.getAxisList() 
    171                 #print var.id, "here" 
    172                 for i in range(ndims):             
    173                     if nappy.cdms_utils.axis_utils.compareAxes(axes[i], caxes[i]) == 0: 
    174                         self.var_bin.append(var) 
    175                         continue 
    176                 # OK, I think they are compatible 
    177                 vars_for_na.append(var) 
    178                  
    179         # Re-order if they previously came from NASA Ames files (i.e. including  
    180         # the attribute 'nasa_ames_var_number') 
    181         ordered_vars = [None] * 1000 
    182         other_vars = [] 
    183         for var in vars_for_na: 
    184             if hasattr(var, "nasa_ames_var_number"): 
    185                 ordered_vars[var.nasa_ames_var_number[0]] = var 
    186             else: 
    187                 other_vars.append(var) 
    188         # Remake vars_for_na now in order 
    189         vars_for_na = [] 
    190         for var in ordered_vars: 
    191             if var != None: vars_for_na.append(var) 
    192         vars_for_na = vars_for_na + other_vars 
    193  
    194         # Now re-order the Auxiliary variables if they previously came from NASA  
    195         # Ames files (i.e. including the attribute 'nasa_ames_aux_var_number') 
    196  
    197         ordered_aux_vars = [None] * 1000 
    198         other_aux_vars = [] 
    199         for var in aux_vars_for_na: 
    200             if hasattr(var, "nasa_ames_aux_var_number"): 
    201                 ordered_aux_vars[var.nasa_ames_aux_var_number[0]] = var 
    202             else: 
    203                 other_aux_vars.append(var) 
    204         # Remake aux_vars_for_na now in order 
    205         aux_vars_for_na = [] 
    206         for var in ordered_aux_vars: 
    207             if var != None: aux_vars_for_na.append(var) 
    208         aux_vars_for_na = aux_vars_for_na + other_aux_vars       
    209         return (vars_for_na, aux_vars_for_na) 
    210  
    211  
    212     def defineNAVars(self, vars): 
    213         """ 
    214         Method to define NASA Ames file object variables and their 
    215         associated metadata. 
    216         """ 
     249                ffi = 1001 
     250        return ffi 
     251 
     252 
     253    def _defineNAVars(self, vars): 
     254        """ 
     255        Method to define NASA Ames file object variables and their 
     256        associated metadata. 
     257        """ 
    217258        self.na_dict["NV"] = len(vars) 
    218259        self.na_dict["VNAME"] = [] 
     
    220261        self.na_dict["VSCAL"] = [] 
    221262        self.na_dict["V"] = [] 
     263 
    222264        for var in vars: 
    223265            name = nappy.cdms_utils.var_utils.getBestName(var) 
    224266            self.na_dict["VNAME"].append(name) 
    225267            miss = nappy.cdms_utils.var_utils.getMissingValue(var) 
    226             if type(miss) not in (float, int, long):  miss = miss[0] 
     268            if type(miss) not in (type(1.2), type(1), type(1L)):   
     269                miss = miss[0] 
    227270            self.na_dict["VMISS"].append(miss) 
    228271            self.na_dict["VSCAL"].append(1) 
    229             # AND THE ARRAY 
    230             # Populate the variable list   
     272            # Populate the variable list with the array 
    231273            self.na_dict["V"].append(var._data) 
    232274 
     
    234276                self.na_dict["NXDEF"] = [] 
    235277                self.na_dict["NX"] = [] 
     278 
    236279                # Create independent variable information 
    237280                self.ax0 = var.getAxis(0) 
    238                 self.na_dict["X"] = [list(self.ax0._data_)] 
     281                self.na_dict["X"] = [self.ax0[:].tolist()] 
    239282                self.na_dict["XNAME"] = [nappy.cdms_utils.var_utils.getBestName(self.ax0)] 
    240283                if len(self.ax0) == 1: 
     
    242285                else: 
    243286                    incr = self.ax0[1] - self.ax0[0] 
    244                     # Set default increment as gap between first two 
    245                     self.na_dict["DX"] = [incr] 
    246                     # Now overwrite it as zero if non-uniform interval in axis 
     287                    # Set default increment as gap between first two 
     288                    self.na_dict["DX"] = [incr] 
     289                    # Now overwrite it as zero if non-uniform interval in axis 
    247290                    for i in range(1, len(self.ax0)): 
    248291                        if (self.ax0[i] - self.ax0[i - 1]) != incr: 
     
    250293                            break 
    251294 
    252                 # Now sort the rest of the axes 
     295                # Now add the rest of the axes to the self.na_dict objects  
    253296                for axis in var.getAxisList()[1:]: 
    254                     self.getAxisDefinition(axis) 
    255  
    256  
    257     def defineNAAuxVars(self, auxVars): 
    258         """ 
    259         Method to define NASA Ames file object auxiliary variables and their 
    260         associated metadata. 
    261         """ 
    262         self.na_dict["NAUXV"] = len(auxVars) 
     297                    self._appendAxisDefinition(axis) 
     298 
     299 
     300    def _defineNAaux_vars(self, aux_vars): 
     301        """ 
     302        Method to define NASA Ames file object auxiliary variables and their 
     303        associated metadata. 
     304        """ 
     305        self.na_dict["NAUXV"] = len(aux_vars) 
    263306        self.na_dict["ANAME"] = [] 
    264307        self.na_dict["AMISS"] = [] 
    265308        self.na_dict["ASCAL"] = [] 
    266309        self.na_dict["A"] = [] 
    267         for var in auxVars: 
     310 
     311        for var in aux_vars: 
    268312            name = nappy.cdms_utils.var_utils.getBestName(var) 
    269313            self.na_dict["ANAME"].append(name) 
    270314            miss = nappy.cdms_utils.var_utils.getMissingValue(var) 
    271             if type(miss) != float:  miss = miss[0] 
     315            if type(miss) != type(1.1):  miss = miss[0] 
    272316            self.na_dict["AMISS"].append(miss) 
    273317            self.na_dict["ASCAL"].append(1) 
    274             # AND THE ARRAY 
    275             # Populate the variable list   
     318            # Populate the variable list with the array 
    276319            self.na_dict["A"].append(var._data) 
    277320 
    278     def getAxisDefinition(self, axis): 
     321    def _appendAxisDefinition(self, axis): 
    279322        """ 
    280323        Method to create the appropriate NASA Ames file object  
    281324        items associated with an axis (independent variable in  
    282         NASA Ames). 
     325        NASA Ames). It appends to the various self.na_dict containers. 
    283326        """ 
    284327        length = len(axis) 
     
    289332            self.na_dict["DX"].append(0) 
    290333            self.na_dict["NXDEF"].append(length) 
    291             self.na_dict["X"].append(list(axis._data_))         
     334            self.na_dict["X"].append(axis[:].tolist())         
    292335            return 
    293336    
     
    297340                self.na_dict["DX"].append(0) 
    298341                self.na_dict["NXDEF"].append(length) 
    299                 self.na_dict["X"].append(list(axis._data_)) 
     342                self.na_dict["X"].append(axis.tolist()) 
    300343                break 
    301         else: 
    302             max_length = length 
    303             if length > 3: max_length = 3 
    304             self.na_dict["DX"].append(incr) 
    305             self.na_dict["NXDEF"].append(max_length) 
    306             self.na_dict["X"].append(axis[:max_length]) 
    307         return 
    308  
    309  
    310     def defineNAGlobals(self): 
     344        else: # If did not break out of the loop 
     345            max_length = length 
     346            if length > 3: max_length = 3 
     347                self.na_dict["DX"].append(incr) 
     348                self.na_dict["NXDEF"].append(max_length) 
     349                self.na_dict["X"].append(axis[:max_length]) 
     350 
     351 
     352    def _defineNAGlobals(self): 
    311353        """ 
    312354        Maps CDMS (NetCDF) global attributes into NASA Ames Header fields. 
    313355        """ 
    314356        # Check if we should add to it with locally set rules 
    315         locally_set_globals = localRules.localGlobalAttributes 
    316         for att in locally_set_globals.keys(): 
     357        local_attributes = nappy.utils.getConfigDict()["local_attributes"] 
     358        for att, value in local_attributes.items(): 
    317359            if not nc_to_na_map.has_key(att): 
    318                 nc_to_na_map[key] = locally_set_globals[key] 
     360                nc_to_na_map[key] = value 
    319361 
    320362        self.extra_comments = [[],[],[]]  # Normal comments, special comments, other comments 
     
    322364 
    323365        for key in self.globals.keys(): 
    324             if key != "first_valid_date_of_data" and type(self.globals[key]) not in (str, float, int): 
     366            if key != "first_valid_date_of_data" and type(self.globals[key]) \ 
     367                                       not in (type("s"), type(1.1), type(1)): 
    325368                continue 
    326369 
     370            # Loop through keys of header/comment items to map 
    327371            if key in nc_to_na_map.keys(): 
    328372                if key == "history": 
    329                     timestring = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) 
    330                     history = "History:\t%s - Converted to NASA Ames format using nappy-%s.\n\t%s" % (timestring, version.version, self.globals[key]) 
     373                    time_string = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) 
     374                    history = "History:\t%s - Converted to NASA Ames format using nappy-%s.\n\t%s" % \ 
     375                                                 (time_string, version.version, self.globals[key]) 
    331376                    history = history.split("\n")  
    332377                    self.history = [] 
     
    337382                     
    338383                elif key == "institution": 
    339                     # If fields came from NA then extract appropriate fields. 
    340                     match = re.match(r"(.*)\s+\(ONAME from NASA Ames file\);\s+(.*)\s+\(ORG from NASA Ames file\)\.", self.globals[key]) 
    341                     if match: 
    342                         self.na_dict["ONAME"] = match.groups()[0] 
    343                         self.na_dict["ORG"] = match.groups()[1] 
    344                     else: 
     384                    # If fields came from NA then extract appropriate fields. 
     385                    match = re.match(r"(.*)\s+\(ONAME from NASA Ames file\);\s+(.*)\s+\(ORG from NASA Ames file\)\.",  
     386                             self.globals[key]) 
     387                    if match: 
     388                        self.na_dict["ONAME"] = match.groups()[0] 
     389                        self.na_dict["ORG"] = match.groups()[1] 
     390                    else: 
    345391                        self.na_dict["ONAME"] = self.globals[key] 
    346                         self.na_dict["ORG"] = self.globals[key]              
    347                      
    348                     # NOte: should probably do the following search and replace on all string lines 
    349                     self.na_dict["ONAME"] = self.na_dict["ONAME"].replace("\n", "  ") 
    350                     self.na_dict["ORG"] = self.na_dict["ORG"].replace("\n", "  ") 
     392                        self.na_dict["ORG"] = self.globals[key]             
     393                    # NOTE: should probably do the following search and replace on all string lines 
     394                    self.na_dict["ONAME"] = self.na_dict["ONAME"].replace("\n", "  ") 
     395                    self.na_dict["ORG"] = self.na_dict["ORG"].replace("\n", "  ") 
    351396                                     
    352397                elif key == "comment": 
    353                     # Need to work out if they are actually comments from NASA Ames in the first place 
    354                     #self.ncom = [self.globals[key]] 
    355                     comLines = self.globals[key].split("\n") 
    356                     normComms = [] 
    357                     normCommFlag = None 
    358                     specComms = [] 
    359                     specCommFlag = None 
    360                     for line in comLines: 
    361                         if line.find("###NASA Ames Special Comments follow###") > -1: 
    362                             specCommFlag = 1 
    363                         elif line.find("###NASA Ames Special Comments end###") > -1: 
    364                             specCommFlag = None 
    365                         elif line.find("###NASA Ames Normal Comments follow###") > -1: 
    366                             normCommFlag = 1 
    367                         elif line.find("###NASA Ames Normal Comments end###") > -1: 
    368                             normCommFlag = None  
    369                         elif specCommFlag == 1: 
    370                             specComms.append(line) 
    371                         elif normCommFlag == 1: 
    372                             normComms.append(line) 
    373                         elif line.find("###Data Section begins on the next line###") > -1: 
    374                             pass 
    375                         else: 
    376                             normComms.append(line)           
     398                    # Need to work out if they are actually comments from NASA Ames in the first place 
     399                    comment_lines = self.globals[key].split("\n") 
     400                    normal_comments = [] 
     401                    normal_comm_flag = None 
     402                    special_comments = [] 
     403                    special_comm_flag = None 
     404 
     405                    for line in comment_lines: 
     406                        if line.find("###NASA Ames Special Comments follow###") > -1: 
     407                            special_comm_flag = 1 
     408                        elif line.find("###NASA Ames Special Comments end###") > -1: 
     409                            special_comm_flag = None 
     410                        elif line.find("###NASA Ames Normal Comments follow###") > -1: 
     411                            normal_comm_flag = 1 
     412                        elif line.find("###NASA Ames Normal Comments end###") > -1: 
     413                            normal_comm_flag = None      
     414                        elif special_comm_flag == 1: 
     415                            special_comments.append(line) 
     416                        elif normal_comm_flag == 1: 
     417                            normal_comments.append(line) 
     418                        elif line.find("###Data Section begins on the next line###") > -1: 
     419                            pass 
     420                        else: 
     421                            normal_comments.append(line)             
    377422                     
    378                     self.extra_comments = [specComms, normComms, []]                 
     423                    self.extra_comments = [special_comments, normal_comments, []]                    
    379424                                     
    380                 elif key == "first_valid_date_of_data": 
    381                     self.na_dict["DATE"] = self.globals[key] 
     425                elif key == "first_valid_date_of_data": 
     426                    self.na_dict["DATE"] = self.globals[key] 
    382427                 
    383428                elif key in ("Conventions", "references"): 
    384429                    #convention_or_reference_comments.append("%s:   %s" % (key, self.globals[key])) 
    385                     self.extra_comments[2].append("%s:   %s" % (key, self.globals[key])) 
     430                    self.extra_comments[2].append("%s:   %s" % (key, self.globals[key])) 
    386431                else: 
    387432                    self.na_dict[nc_to_na_map[key]] = self.globals[key] 
    388433            else: 
    389434                self.extra_comments[2].append("%s:   %s" % (key, self.globals[key])) 
    390         #self.extra_comments 
    391435        return 
    392436 
    393437 
    394     def defineNAComments(self, normal_comments=[], special_comments=[]): 
    395         """ 
    396         Defines the Special and Normal comments sections in the NASA Ames file  
    397         object - including information gathered from the defineNAGlobals method. 
    398         """ 
     438    def _defineNAComments(self, normal_comments=[], special_comments=[]): 
     439        """ 
     440        Defines the Special and Normal comments sections in the NASA Ames file  
     441        object - including information gathered from the defineNAGlobals method. 
     442        """ 
    399443         
    400444        if hasattr(self, "ncom"):  normal_comments = self.ncom + normal_comments 
    401         NCOM = [] 
     445 
     446        NCOM = [] 
    402447        for ncom in normal_comments: 
    403448            NCOM.append(ncom) 
     449 
    404450        if len(NCOM) > 0:   NCOM.append("") 
    405451         
    406         if len(self.extra_comments[2]) > 0: 
    407             for excom in self.extra_comments[2]: 
    408                 NCOM.append(excom) 
     452        if len(self.extra_comments[2]) > 0: 
     453            for excom in self.extra_comments[2]: 
     454                NCOM.append(excom) 
    409455         
    410456        if len(self.extra_comments[1]) > 0:   
    411             NCOM.append("Additional Global Attributes defined in the source file and not translated elsewhere:") 
     457            NCOM.append("Additional Global Attributes defined in the source file and not translated elsewhere:") 
    412458            for excom in self.extra_comments[1]: 
    413459                NCOM.append(excom) 
     
    417463                NCOM.append(h) 
    418464         
    419         if len(NCOM) > 0: 
    420             NCOM.insert(0, "###NASA Ames Normal Comments follow###") 
    421             NCOM.append("") 
    422             NCOM.append("###NASA Ames Normal Comments end###") 
    423         NCOM.append("###Data Section begins on the next line###") 
    424  
    425         specCommentsFlag = None 
    426         SCOM = [] 
    427         special_comments = self.extra_comments[0] 
    428         if len(special_comments) > 0:  
    429             SCOM = ["###NASA Ames Special Comments follow###"] 
    430             specCommentsFlag = 1 
     465        if len(NCOM) > 0: 
     466            NCOM.insert(0, "###NASA Ames Normal Comments follow###") 
     467            NCOM.append("") 
     468            NCOM.append("###NASA Ames Normal Comments end###") 
     469            NCOM.append("###Data Section begins on the next line###") 
     470 
     471        spec_comm_flag = None 
     472        SCOM = [] 
     473        special_comments = self.extra_comments[0] 
     474        if len(special_comments) > 0:  
     475            SCOM = ["###NASA Ames Special Comments follow###"] 
     476 
     477            spec_comm_flag = 1 
    431478        for scom in special_comments: 
    432479            SCOM.append(scom) 
    433480 
    434  
    435         #used_var_atts=("name", "long_name", "standard_name", "id",  
    436             #    "missing_value", "fill_value", "units",  
    437                 #"nasa_ames_var_number", "nasa_ames_aux_var_number") 
    438481        used_var_atts = ("id",  "missing_value", "fill_value", "units",  
    439482                   "nasa_ames_var_number", "nasa_ames_aux_var_number") 
    440         varCommentsFlag = None 
     483        var_comm_flag = None 
    441484 
    442485        # Create a string for the Special comments to hold rank-zero vars 
    443         rank_zero_varsString = [] 
    444         for var in self.rank_zero_vars: 
    445             rank_zero_varsString.append("\tVariable %s: %s" % (var.id, nappy.cdms_utils.var_utils.getBestName(var))) 
    446             for att in var.attributes.keys(): 
    447                 value = var.attributes[att] 
    448                 if type(value) in (str, float, int): 
    449                     rank_zero_varsString.append("\t\t%s = %s" % (att, var.attributes[att])) 
    450             #print "VALUES", dir(var), var._data ; rank_zero_varsString.append("\t\tvalue  =  %s" % var._data) 
     486        rank_zero_vars_string = [] 
     487        for var in self.rank_zero_vars: 
     488            rank_zero_vars_string.append("\tVariable %s: %s" % (var.id, nappy.cdms_utils.var_utils.getBestName(var))) 
     489 
     490        for att in var.attributes.keys(): 
     491            value = var.attributes[att] 
     492            if type(value) in (type("s"), type(1.0), type(1)): 
     493                rank_zero_vars_string.append("\t\t%s = %s" % (att, var.attributes[att])) 
    451494         
    452         if len(rank_zero_varsString) > 0: 
    453             rank_zero_varsString.insert(0, "###Singleton Variables defined in the source file follow###") 
    454             rank_zero_varsString.append("###Singleton Variables defined in the source file end###") 
     495        if len(rank_zero_vars_string) > 0: 
     496            rank_zero_vars_string.insert(0, "###Singleton Variables defined in the source file follow###") 
     497            rank_zero_vars_string.append("###Singleton Variables defined in the source file end###") 
    455498 
    456499        for var in self.ordered_vars: 
    457500            varflag = "unused" 
    458501            name = nappy.cdms_utils.var_utils.getBestName(var) 
     502 
    459503            for scom,value in var.attributes.items(): 
    460504                if type(value) in (type([]), type(Numeric.array([0]))) and len(value) == 1: 
    461505                    value = value[0] 
    462                 if type(value) in (str, float, int) and scom not in used_var_atts: 
     506 
     507                if type(value) in (type("s"), type(1.1), type(1)) and scom not in used_var_atts: 
    463508                    if varflag == "unused": 
    464                         if varCommentsFlag == None: 
    465                             varCommentsFlag = 1 
    466                             if specCommentsFlag == None: 
    467                                 SCOM = ["###NASA Ames Special Comments follow###"] + rank_zero_varsString 
     509                        if var_comm_flag == None: 
     510                            var_comm_flag = 1 
     511                                    if spec_comm_flag == None: 
     512                                            SCOM = ["###NASA Ames Special Comments follow###"] + rank_zero_vars_string 
    468513                            SCOM.append("Additional Variable Attributes defined in the source file and not translated elsewhere:") 
    469514                            SCOM.append("###Variable attributes from source (NetCDF) file follow###") 
     
    472517                    SCOM.append("\t\t%s = %s" % (scom, value)) 
    473518 
    474         if varCommentsFlag == 1:  SCOM.append("###Variable attributes from source (NetCDF) file end###") 
    475         if specCommentsFlag == 1: 
    476             SCOM.append("###NASA Ames Special Comments end###") 
    477  
    478         """used_var_atts = ("name", "long_name", "standard_name", "id", "missing_value", "fill_value", "units") 
    479         for var in self.vars: 
    480             for scom,value in var.attributes.items(): 
    481                 name = nappy.cdms_utils.var_utils.getBestName(var) 
    482                 if type(value) in (str, float, int) and scom not in used_var_atts: 
    483                     SCOM.append("\t%s: %s - %s" % (name, scom, value))""" 
     519        if var_comm_flag == 1:  SCOM.append("###Variable attributes from source (NetCDF) file end###") 
     520        if spec_comm_flag == 1: 
     521            SCOM.append("###NASA Ames Special Comments end###") 
    484522 
    485523        # Strip out empty lines (or returns) 
    486         NCOM_cleaned = [] 
    487         SCOM_cleaned = [] 
    488         #hiddenNewLineCount1 = 0 
    489         for c in NCOM: 
    490             if c.strip() not in ("", " ", "  "): 
    491                 #hiddenNewLineCount1 = hiddenNewLineCount1 + c.count("\n") 
    492                 # Replace new lines within one attribute with a newline and tab so easier to read 
    493                 lines = c.split("\n") 
    494                 for line in lines: 
    495                     if line != lines[0]: line = "\t" + line 
    496                     NCOM_cleaned.append(line) 
    497                  
    498         #hiddenNewLineCount2 = 0         
    499         for c in SCOM: 
    500             if c.strip() not in ("", " ", "  "):                 
    501                 #hiddenNewLineCount2 = hiddenNewLineCount2 + c.count("\n") 
    502                 # Replace new lines within one attribute with a newline and tab so easier to read 
    503                 #c = c.replace("\n", "\n\t") 
    504                 #SCOM_cleaned.append(c) 
    505                 lines = c.split("\n") 
    506                 for line in lines: 
    507                     if line != lines[0]: line = "\t" + line 
    508                     SCOM_cleaned.append(line) 
     524        NCOM_cleaned = [] 
     525        SCOM_cleaned = [] 
     526 
     527        for c in NCOM: 
     528            if c.strip() not in ("", " ", "  "): 
     529                # Replace new lines within one attribute with a newline and tab so easier to read 
     530                lines = c.split("\n") 
     531                for line in lines: 
     532                    if line != lines[0]:  
     533                        line = "\t" + line 
     534                    NCOM_cleaned.append(line) 
     535                         
     536        for c in SCOM: 
     537            if c.strip() not in ("", " ", "  "):                 
     538                        # Replace new lines within one attribute with a newline and tab so easier to read 
     539                lines = c.split("\n") 
     540                for line in lines: 
     541                    if line != lines[0]:  
     542                        line = "\t" + line 
     543                    SCOM_cleaned.append(line) 
    509544                     
    510545        self.na_dict["NCOM"] = NCOM_cleaned 
    511         self.na_dict["NNCOML"] = len(self.na_dict["NCOM"])# + hiddenNewLineCount1 
     546        self.na_dict["NNCOML"] = len(self.na_dict["NCOM"]) 
    512547        self.na_dict["SCOM"] = SCOM_cleaned 
    513         self.na_dict["NSCOML"] = len(self.na_dict["SCOM"])# + hiddenNewLineCount2 
     548        self.na_dict["NSCOML"] = len(self.na_dict["SCOM"]) 
    514549        return 
    515550 
    516551 
    517     def defineGeneralHeader(self, header_items={}): 
    518         """ 
    519         Defines known header items and overwrites any with header_items  
    520         key/value pairs. 
    521         """ 
    522         # Check if DATE field previously known in NASA Ames file 
    523         time_now = time.strftime("%Y %m %d", time.localtime(time.time())).split() 
    524         if not self.na_dict.has_key("RDATE"): 
    525             self.na_dict["RDATE"] = time_now 
     552    def _defineGeneralHeader(self, header_items={}): 
     553        """ 
     554        Defines known header items and overwrites any with header_items  
     555        key/value pairs. 
     556        """ 
     557        # Check if DATE field previously known in NASA Ames file 
     558        time_now = time.strftime("%Y %m %d", time.localtime(time.time())).split() 
     559        if not self.na_dict.has_key("RDATE"): 
     560            self.na_dict["RDATE"] = time_now 
    526561         
    527562        if self.ax0.isTime(): 
    528563            # Get first date in list 
    529             try: 
     564            try: 
    530565                (unit, start_date) = re.match("(\w+)\s+?since\s+?(\d+-\d+-\d+)", self.ax0.units).groups()             
    531566                comptime = cdtime.s2c(start_date) 
    532567                first_day = comptime.add(self.na_dict["X"][0][0], getattr(cdtime, unit.capitalize())) 
    533568                self.na_dict["DATE"] = string.replace(str(first_day).split(" ")[0], "-", " ").split() 
    534             except: 
    535                 msg = "Nappy Warning: Could not get the first date in the file. You will need to manually edit the output file." 
    536                 print msg 
    537                 self.output_message.append(msg) 
    538                 self.na_dict["DATE"] = ("DATE", "NOT", "KNOWN") 
     569            except: 
     570                msg = "Nappy Warning: Could not get the first date in the file. You will need to manually edit the output file." 
     571                print msg 
     572                self.output_message.append(msg) 
     573                self.na_dict["DATE"] = ("DATE", "NOT", "KNOWN") 
    539574        else:  
    540575            if not self.na_dict.has_key("DATE"): 
    541                 msg = "Nappy Warning: Could not get the first date in the file. You will need to manually edit the output file." 
    542                 print msg 
    543                 self.output_message.append(msg) 
     576                msg = "Nappy Warning: Could not get the first date in the file. You will need to manually edit the output file." 
     577            print msg 
     578            self.output_message.append(msg) 
    544579                self.na_dict["DATE"] = ("DATE", "NOT", "KNOWN") 
     580 
    545581        self.na_dict["IVOL"] = 1 
    546582        self.na_dict["NVOL"] = 1 
     
    548584             self.na_dict[key] = header_items[key] 
    549585        return 
    550  
    551  
  • nappy/trunk/nappy/nc_interface/na_to_nc.py

    r3329 r3351  
    3333        >>>    c = na_to_nc("old_file.na")  
    3434        >>>    c.convert() 
    35         >>>    c.writeFile("new_file.nc")          
     35        >>>    c.write("new_file.nc")          
    3636        """ 
    3737        # First open na_file if it is a file rather than an na_file object 
     
    4646 
    4747 
    48     def writeFile(self, file_name, mode="w"): 
     48    def write(self, file_name, mode="w"): 
    4949        """ 
    5050        Writes the NASA Ames content that has been converted into CDMS objects to a 
Note: See TracChangeset for help on using the changeset viewer.