예제 #1
0
    def handle(self, *args, **options):
        try:
            self.file_name = args[0]
            in_file = dirname(__file__) + "/" + self.file_name
            err_file = dirname(__file__) + "/" + self.file_name + ".err"
            self.verbose = options.get('verbose')
            self.user_id = args[1]
            if len(args) > 2:
                self.base_srid = int(args[2])
                self.tf = CoordTransform(SpatialReference(self.base_srid),
                                         SpatialReference(4326))
                print "Using transformaton object: %s" % self.tf
            else:
                self.base_srid = 4326
            if len(args) > 3:
                self.readonly = bool(args[3])
                print "Setting readonly flag to %s" % self.readonly
            else:
                self.readonly = False
        except:
            print "Arguments:  Input_File_Name.[dbf|csv], Data_Owner_User_Id, (Base_SRID optional)"
            print "Options:    --verbose"
            return

        self.err_writer = csv.writer(open(err_file, 'wb'))

        if self.file_name.endswith('.csv'):
            rows = self.get_csv_rows(in_file)
        if self.file_name.endswith('.dbf'):
            rows = self.get_dbf_rows(in_file)

        self.data_owner = User.objects.get(pk=self.user_id)
        self.updater = User.objects.get(pk=1)

        self.import_event = ImportEvent(file_name=self.file_name)
        self.import_event.save()

        print 'Importing %d records' % len(rows)
        for i, row in enumerate(rows):
            self.handle_row(row)

            j = i + 1
            if j % 50 == 0:
                print 'Loaded %d...' % j
            self.log_verbose("item %d" % i)

        print "Finished data load. "

        print "Calculating new species tree counts... "
        for s in Species.objects.all():
            s.save()
        print "Done."
예제 #2
0
파일: uimport.py 프로젝트: nittt3/Code
    def handle(self, *args, **options):
        try:    
            self.file_name = args[0]
            in_file = self.file_name
            err_file = in_file + ".err"
            self.verbose = options.get('verbose')
            self.user_id = args[1]
            if len(args) > 2:
                self.base_srid = int(args[2])
                self.tf = CoordTransform(SpatialReference(self.base_srid), SpatialReference(4326))
                print "Using transformaton object: %s" % self.tf
            else:
                self.base_srid = 4326
	    if len(args) > 3:
		self.readonly = bool(args[3])
                print "Setting readonly flag to %s" % self.readonly
	    else:
		self.readonly = False
        except:
            print "Arguments:  Input_File_Name.[dbf|csv], Data_Owner_User_Id, (Base_SRID optional)"
            print "Options:    --verbose"
            return
        
        self.err_writer = csv.writer(open(err_file, 'wb'))
        
        if self.file_name.endswith('.csv'):
            rows = self.get_csv_rows(in_file)
        if self.file_name.endswith('.dbf'):
            rows = self.get_dbf_rows(in_file)

        self.data_owner = User.objects.get(pk=self.user_id)
        self.updater = User.objects.get(pk=1)
        
        self.import_event = ImportEvent(file_name=self.file_name)
        self.import_event.save()
        
        print 'Importing %d records' % len(rows)
        for i, row in enumerate(rows):
            if i < 420:
                continue

            self.handle_row(row)
            
            j = i + 1
            if j % 50 == 0:
               print 'Loaded %d...' % j
            self.log_verbose("item %d" % i)
        
        print "Finished data load. "

        print "Calculating new species tree counts... "
        for s in Species.objects.all():
            s.save()
        print "Done."
예제 #3
0
class Command(BaseCommand):
    args = '<input_file_name, data_owner_id, base_srid, read_only>'
    option_list = BaseCommand.option_list + (make_option(
        '--verbose',
        action='store_true',
        dest='verbose',
        default=False,
        help='Show verbose debug text'), )

    def get_dbf_rows(self, in_file):
        reader = dbf.Dbf(in_file)
        print 'Opening input file: %s ' % in_file

        self.headers = reader.fieldNames
        self.err_writer.writerow(self.headers)

        print 'Converting input file to dictionary'
        rows = []
        for dbf_row in reader:
            d = {}
            for name in self.headers:
                d[name] = dbf_row[name]
            rows.append(d)
        return rows

    def get_csv_rows(self, in_file):
        reader = csv.DictReader(open(in_file, 'r'), restval=123)
        print 'Opening input file: %s ' % in_file

        rows = list(reader)

        self.headers = reader.fieldnames
        self.err_writer.writerow(self.headers)

        return rows

    def handle(self, *args, **options):
        try:
            self.file_name = args[0]
            in_file = dirname(__file__) + "/" + self.file_name
            err_file = dirname(__file__) + "/" + self.file_name + ".err"
            self.verbose = options.get('verbose')
            self.user_id = args[1]
            if len(args) > 2:
                self.base_srid = int(args[2])
                self.tf = CoordTransform(SpatialReference(self.base_srid),
                                         SpatialReference(4326))
                print "Using transformaton object: %s" % self.tf
            else:
                self.base_srid = 4326
            if len(args) > 3:
                self.readonly = bool(args[3])
                print "Setting readonly flag to %s" % self.readonly
            else:
                self.readonly = False
        except:
            print "Arguments:  Input_File_Name.[dbf|csv], Data_Owner_User_Id, (Base_SRID optional)"
            print "Options:    --verbose"
            return

        self.err_writer = csv.writer(open(err_file, 'wb'))

        if self.file_name.endswith('.csv'):
            rows = self.get_csv_rows(in_file)
        if self.file_name.endswith('.dbf'):
            rows = self.get_dbf_rows(in_file)

        self.data_owner = User.objects.get(pk=self.user_id)
        self.updater = User.objects.get(pk=1)

        self.import_event = ImportEvent(file_name=self.file_name)
        self.import_event.save()

        print 'Importing %d records' % len(rows)
        for i, row in enumerate(rows):
            self.handle_row(row)

            j = i + 1
            if j % 50 == 0:
                print 'Loaded %d...' % j
            self.log_verbose("item %d" % i)

        print "Finished data load. "

        print "Calculating new species tree counts... "
        for s in Species.objects.all():
            s.save()
        print "Done."

    def log_verbose(self, msg):
        if self.verbose: print msg

    def log_error(self, msg, row):
        print "ERROR: %s" % msg
        columns = [row[s] for s in self.headers]
        self.err_writer.writerow(columns)

    def check_coords(self, row):
        try:
            x = float(row.get('POINT_X', 0))
            y = float(row.get('POINT_Y', 0))
        except:
            self.log_error("  Invalid coords, might not be numbers", row)
            return (False, 0, 0)

        ok = x and y
        if not ok:
            self.log_error("  Invalid coords", row)
        self.log_verbose("  Passed coordinate check")
        return (ok, x, y)

    def check_species(self, row):
        # locate the species and instanciate the tree instance
        if not row.get('SCIENTIFIC') and not row.get('GENUS'):
            self.log_verbose("  No species information")
            return (True, None)

        if row.get('SCIENTIFIC'):
            name = str(row['SCIENTIFIC']).strip()
            species = Species.objects.filter(scientific_name__iexact=name)
            self.log_verbose("  Looking for species: %s" % name)
        else:
            genus = str(row['GENUS']).strip()
            species = ''
            cultivar = ''
            if row.get('SPECIES'):
                species = str(row['SPECIES']).strip()
            if row.get('CULTIVAR'):
                cultivar = str(row['CULTIVAR']).strip()
            species = Species.objects.filter(genus__iexact=genus).filter(
                species__iexact=species).filter(cultivar_name__iexact=cultivar)
            self.log_verbose("  Looking for species: %s %s %s" %
                             (genus, species, cultivar))

        if species:  #species match found
            self.log_verbose("  Found species %r" % species[0])
            return (True, species)

        #species data but no match, check it manually
        self.log_error("ERROR:  Unknown species %r" % name, row)
        return (False, None)

    def check_tree_info(self, row):
        tree_info = False
        fields = [
            'STEWARD', 'SPONSOR', 'DATEPLANTED', 'DIAMETER', 'HEIGHT',
            'CANOPYHEIGHT', 'CONDITION', 'CANOPYCONDITION', 'PROJECT_1',
            'PROJECT_2', 'PROJECT_3', 'OWNER'
        ]

        for f in fields:
            # field exists and there's something in it
            if row.get(f) and str(row[f]).strip():
                tree_info = True
                self.log_verbose(
                    '  Found tree data in field %s, creating a tree' % f)
                break

        return tree_info

    def check_proximity(self, plot, tree, species, row):
        # check for nearby plots
        collisions = plot.validate_proximity(True, 0)

        # if there are no collisions, then proceed as planned
        if not collisions:
            self.log_verbose("  No collisions found")
            return (True, plot, tree)
        self.log_verbose("  Initial proximity test count: %d" %
                         collisions.count())

        # exclude collisions from the same file we're working in
        collisions = collisions.exclude(import_event=self.import_event)
        if not collisions:
            self.log_verbose("  All collisions are from this import file")
            return (True, plot, tree)
        self.log_verbose("  Secondary proximity test count: %d" %
                         collisions.count())

        # if we have multiple collitions, check for same species or unknown species
        # and try to associate with one of them otherwise abort
        if collisions.count() > 1:
            # get existing trees for the plots that we collided with
            tree_ids = []
            for c in collisions:
                if c.current_tree():
                    tree_ids.append(c.current_tree().id)

            trees = Tree.objects.filter(id__in=tree_ids)

            # Precedence: single same species, single unknown
            # return false for all others and log
            if species:
                same = trees.filter(species=species[0])
                if same.count() == 1 and same[0].species == species[0]:
                    self.log_verbose(
                        "  Using single nearby plot with tree of same species")
                    return (True, c, same[0])

            unk = trees.filter(species=None)

            if unk.count() == 1:
                self.log_verbose(
                    "  Using single nearby plot with tree of unknown species")
                return (True, c, unk[0])

            self.log_error(
                "ERROR:  Proximity test failed (near %d plots)" %
                collisions.count(), row)
            return (False, None, None)

        # one nearby match found, use it as base
        plot = collisions[0]
        plot_tree = plot.current_tree()
        self.log_verbose("  Found one tree nearby")

        # if the nearby plot doesn't have a tree, don't bother doing species matching
        if not plot_tree:
            self.log_verbose(
                "  No tree found for plot, using %d as base plot record" %
                plot.id)
            return (True, plot, tree)

        # if neither have a species, then we're done and we need to use
        # the tree we collided with.
        if not plot_tree.species and not species:
            self.log_verbose(
                "  No species info for either record, using %d as base tree record"
                % plot_tree.id)
            return (True, plot, plot_tree)

        # if only the new one has a species, update the tree we collided
        # with and then return it
        if not plot_tree.species:
            # we need to update the collision tree with the new species
            plot_tree.set_species(species[0].id, False)  # save later
            self.log_verbose("  Species match, using update file species: %s" %
                             species[0])
            return (True, plot, plot_tree)

        # if only the collision tree has a species, we're done.
        if not species or species.count() == 0:
            self.log_verbose(
                "  No species info for import record, using %d as base record"
                % plot_tree.id)
            return (True, plot, plot_tree)

        # in this case, both had a species. we should check to see if
        # the species are the same.
        if plot_tree.species != species[0]:
            # now that we have a new species, we want to update the
            # collision tree's species and delete all the old status
            # information.
            self.log_verbose(
                "  Species do not match, using update file species: %s" %
                species[0])
            plot_tree.set_species(species[0].id, False)
            plot_tree.dbh = None
            plot_tree.height = None
            plot_tree.canopy_height = None
            plot_tree.condition = None
            plot_tree.canopy_condition = None
        return (True, plot, plot_tree)

    def handle_row(self, row):
        self.log_verbose(row)

        # check the physical location
        ok, x, y = self.check_coords(row)
        if not ok: return

        plot = Plot()

        try:
            if self.base_srid != 4326:
                geom = Point(x, y, srid=self.base_srid)
                geom.transform(self.tf)
                self.log_verbose(geom)
                plot.geometry = geom
            else:
                plot.geometry = Point(x, y, srid=4326)
        except:
            self.log_error("ERROR: Geometry failed to transform", row)
            return

        # check the species (if any)
        ok, species = self.check_species(row)
        if not ok: return

        # check for tree info, should we create a tree or just a plot
        if species or self.check_tree_info(row):
            tree = Tree(plot=plot)
        else:
            tree = None

        if tree and species:
            tree.species = species[0]

        # check the proximity (try to match up with existing trees)
        # this may return a different plot/tree than created just above,
        # so don't set anything else on either until after this point
        ok, plot, tree = self.check_proximity(plot, tree, species, row)
        if not ok: return

        if row.get('ADDRESS') and not plot.address_street:
            plot.address_street = str(row['ADDRESS']).title()
            plot.geocoded_address = str(row['ADDRESS']).title()

        if not plot.geocoded_address:
            plot.geocoded_address = ""

        # FIXME: get this from the config?
        plot.address_state = 'CA'
        plot.import_event = self.import_event
        plot.last_updated_by = self.updater
        plot.data_owner = self.data_owner
        plot.owner_additional_properties = self.file_name
        plot.readonly = self.readonly

        if row.get('PLOTTYPE'):
            for k, v in Choices().get_field_choices('plot_type'):
                if v == row['PLOTTYPE']:
                    plot.type = k
                    break

        if row.get('PLOTLENGTH'):
            plot.length = row['PLOTLENGTH']

        if row.get('PLOTWIDTH'):
            plot.width = row['PLOTWIDTH']

        if row.get('ID'):
            plot.owner_orig_id = row['ID']

        if row.get('ORIGID'):
            plot.owner_additional_properties = "ORIGID=" + str(row['ORIGID'])

        # if powerline is specified, then we want to set our boolean
        # attribute; otherwise leave it alone.
        powerline = row.get('POWERLINE')
        if powerline is None or powerline.strip() == "":
            pass
        elif powerline is True or powerline.lower(
        ) == "true" or powerline.lower() == 'yes':
            plot.powerline_conflict_potential = 1
        else:
            plot.powerline_conflict_potential = 2

        sidewalk_damage = row.get('SIDEWALK')
        if sidewalk_damage is None or sidewalk_damage.strip() == "":
            pass
        elif sidewalk_damage is True or sidewalk_damage.lower(
        ) == "true" or sidewalk_damage.lower() == 'yes':
            plot.sidewalk_damage = 2
        else:
            plot.sidewalk_damage = 1

        plot.quick_save()

        pnt = plot.geometry
        n = Neighborhood.objects.filter(geometry__contains=pnt)
        z = ZipCode.objects.filter(geometry__contains=pnt)

        plot.neighborhoods = ""
        plot.neighborhood.clear()
        plot.zipcode = None

        if n:
            for nhood in n:
                if nhood:
                    plot.neighborhoods = plot.neighborhoods + " " + nhood.id.__str__(
                    )
                    plot.neighborhood.add(nhood)

        if z: plot.zipcode = z[0]

        if tree:
            tree.plot = plot
            tree.readonly = self.readonly
            tree.import_event = self.import_event
            tree.last_updated_by = self.updater

            if row.get('OWNER'):
                tree.tree_owner = str(row["OWNER"])

            if row.get('STEWARD'):
                tree.steward_name = str(row["STEWARD"])

            if row.get('SPONSOR'):
                tree.sponsor = str(row["SPONSOR"])

            if row.get('DATEPLANTED'):
                date = str(row['DATEPLANTED'])
                date = datetime.strptime(date, "%m/%d/%Y")
                tree.date_planted = date.strftime("%Y-%m-%d")

            if row.get('DIAMETER'):
                tree.dbh = float(row['DIAMETER'])

            if row.get('HEIGHT'):
                tree.height = float(row['HEIGHT'])

            if row.get('CANOPYHEIGHT'):
                tree.canopy_height = float(row['CANOPYHEIGHT'])

            if row.get('CONDITION'):
                for k, v in Choices().get_field_choices('condition'):
                    if v == row['CONDITION']:
                        tree.condition = k
                        break

            if row.get('CANOPYCONDITION'):
                for k, v in Choices().get_field_choices('canopy_condition'):
                    if v == row['CANOPYCONDITION']:
                        tree.canopy_condition = k
                        break

            tree.quick_save()

            if row.get('PROJECT_1'):
                for k, v in Choices().get_field_choices('local'):
                    if v == row['PROJECT_1']:
                        local = TreeFlags(key=k,
                                          tree=tree,
                                          reported_by=self.updater)
                        local.save()
                        break
            if row.get('PROJECT_2'):
                for k, v in Choices().get_field_choices('local'):
                    if v == row['PROJECT_2']:
                        local = TreeFlags(key=k,
                                          tree=tree,
                                          reported_by=self.updater)
                        local.save()
                        break
            if row.get('PROJECT_3'):
                for k, v in Choices().get_field_choices('local'):
                    if v == row['PROJECT_3']:
                        local = TreeFlags(key=k,
                                          tree=tree,
                                          reported_by=self.updater)
                        local.save()
                        break

            # rerun validation tests and store results
            tree.validate_all()
예제 #4
0
class Command(BaseCommand):
    args = '<input_file_name, data_owner_id, base_srid, read_only>'
    option_list = BaseCommand.option_list + (
        make_option('--verbose',
            action='store_true',
            dest='verbose',
            default=False,
            help='Show verbose debug text'),
    )

    def get_dbf_rows(self, in_file):
        reader = dbf.Dbf(in_file)
        print 'Opening input file: %s ' % in_file

        self.headers = reader.fieldNames
        self.err_writer.writerow(self.headers)
        
        print 'Converting input file to dictionary'
        rows = []
        for dbf_row in reader:
            d = {}
            for name in self.headers:
                d[name] = dbf_row[name]
            rows.append(d)
        return rows
    
    def get_csv_rows(self, in_file):
        reader = csv.DictReader(open(in_file, 'r' ), restval=123)
        print 'Opening input file: %s ' % in_file

        rows = list(reader)
                
        self.headers = reader.fieldnames
        self.err_writer.writerow(self.headers)        
                
        return rows
    
    def handle(self, *args, **options):
        try:    
            self.file_name = args[0]
            in_file = dirname(__file__) + "/" + self.file_name
            err_file = dirname(__file__) + "/" + self.file_name + ".err"
            self.verbose = options.get('verbose')
            self.user_id = args[1]
            if len(args) > 2:
                self.base_srid = int(args[2])
                self.tf = CoordTransform(SpatialReference(self.base_srid), SpatialReference(4326))
                print "Using transformaton object: %s" % self.tf
            else:
                self.base_srid = 4326
	    if len(args) > 3:
		self.readonly = bool(args[3])
                print "Setting readonly flag to %s" % self.readonly
	    else:
		self.readonly = False
        except:
            print "Arguments:  Input_File_Name.[dbf|csv], Data_Owner_User_Id, (Base_SRID optional)"
            print "Options:    --verbose"
            return
        
        self.err_writer = csv.writer(open(err_file, 'wb'))
        
        if self.file_name.endswith('.csv'):
            rows = self.get_csv_rows(in_file)
        if self.file_name.endswith('.dbf'):
            rows = self.get_dbf_rows(in_file)

        self.data_owner = User.objects.get(pk=self.user_id)
        self.updater = User.objects.get(pk=1)
        
        self.import_event = ImportEvent(file_name=self.file_name)
        self.import_event.save()
        
        print 'Importing %d records' % len(rows)
        for i, row in enumerate(rows):
            self.handle_row(row)
            
            j = i + 1
            if j % 50 == 0:
               print 'Loaded %d...' % j
            self.log_verbose("item %d" % i)
        
        print "Finished data load. "

        print "Calculating new species tree counts... "
        for s in Species.objects.all():
            s.save()
        print "Done."
    
    def log_verbose(self, msg):
        if self.verbose: print msg
    
    def log_error(self, msg, row):
        print "ERROR: %s" % msg
        columns = [row[s] for s in self.headers]
        self.err_writer.writerow(columns)
    
    def check_coords(self, row):
        try:
            x = float(row.get('POINT_X', 0))
            y = float(row.get('POINT_Y', 0))
        except:
            self.log_error("  Invalid coords, might not be numbers", row)
            return (False, 0, 0)

        ok = x and y
        if not ok:
            self.log_error("  Invalid coords", row)
        self.log_verbose("  Passed coordinate check")
        return (ok, x, y)

    def check_species(self, row):
        # locate the species and instanciate the tree instance
        if not row.get('SCIENTIFIC') and not row.get('GENUS'):            
            self.log_verbose("  No species information")
            return (True, None)

        if row.get('SCIENTIFIC'):
            name = str(row['SCIENTIFIC']).strip()
            species = Species.objects.filter(scientific_name__iexact=name)
            self.log_verbose("  Looking for species: %s" % name)
        else:
            genus = str(row['GENUS']).strip()
            species = ''
            cultivar = ''
            gender = ''
            name = genus
            if row.get('SPECIES'):
                species = str(row['SPECIES']).strip()
                name = name + " " + species
            if row.get('CULTIVAR'):
                cultivar = str(row['CULTIVAR']).strip()
                name = name + " " + cultivar
            if row.get('GENDER'):
                gender = str(row['GENDER']).strip()
                name = name + " " + gender
            species = Species.objects.filter(genus__iexact=genus).filter(species__iexact=species).filter(cultivar_name__iexact=cultivar).filter(gender__iexact=gender)
            self.log_verbose("  Looking for species: %s %s %s %s" % (genus, species, cultivar, gender))
        

        if species: #species match found
            self.log_verbose("  Found species %r" % species[0])
            return (True, species)
            
        #species data but no match, check it manually
        self.log_error("ERROR:  Unknown species %r" % name, row) 
        return (False, None)

    def check_tree_info(self, row):
        tree_info = False
        fields = ['STEWARD', 'SPONSOR', 'DATEPLANTED', 'DIAMETER', 'HEIGHT', 'CANOPYHEIGHT', 
                  'CONDITION', 'CANOPYCONDITION', 'PROJECT_1', 'PROJECT_2', 'PROJECT_3', 'OWNER']
        
        for f in fields:
            # field exists and there's something in it
            if row.get(f) and str(row[f]).strip():
                tree_info = True
                self.log_verbose('  Found tree data in field %s, creating a tree' % f)
                break
        
        return tree_info

    def check_proximity(self, plot, tree, species, row):
        # check for nearby plots
        collisions = plot.validate_proximity(True, 0)
        
        # if there are no collisions, then proceed as planned
        if not collisions:
            self.log_verbose("  No collisions found")
            return (True, plot, tree)
        self.log_verbose("  Initial proximity test count: %d" % collisions.count())
        
        # exclude collisions from the same file we're working in
        collisions = collisions.exclude(import_event=self.import_event)
        if not collisions:
            self.log_verbose("  All collisions are from this import file")
            return (True, plot, tree)                
        self.log_verbose("  Secondary proximity test count: %d" % collisions.count())
        
        # if we have multiple collitions, check for same species or unknown species
        # and try to associate with one of them otherwise abort
        if collisions.count() > 1:
            # get existing trees for the plots that we collided with
            tree_ids = []             
            for c in collisions:
                if c.current_tree():
                    tree_ids.append(c.current_tree().id)

            trees = Tree.objects.filter(id__in=tree_ids)

            # Precedence: single same species, single unknown 
            # return false for all others and log
            if species:                
                same = trees.filter(species=species[0])            
                if same.count() == 1 and same[0].species == species[0]:
                    self.log_verbose("  Using single nearby plot with tree of same species")
                    return (True, c, same[0])
            
            unk = trees.filter(species=None)
                
            if unk.count() == 1:
                self.log_verbose("  Using single nearby plot with tree of unknown species")
                return (True, c,  unk[0])
            
            self.log_error("ERROR:  Proximity test failed (near %d plots)" % collisions.count(), row)
            return (False, None, None)

        # one nearby match found, use it as base
        plot = collisions[0]
        plot_tree = plot.current_tree()
        self.log_verbose("  Found one tree nearby")

        # if the nearby plot doesn't have a tree, don't bother doing species matching
        if not plot_tree: 
            self.log_verbose("  No tree found for plot, using %d as base plot record" % plot.id)
            return (True, plot, tree)

        # if neither have a species, then we're done and we need to use
        # the tree we collided with.
        if not plot_tree.species and not species:
            self.log_verbose("  No species info for either record, using %d as base tree record" % plot_tree.id)
            return (True, plot, plot_tree)

        # if only the new one has a species, update the tree we collided
        # with and then return it
        if not plot_tree.species:
            # we need to update the collision tree with the new species
            plot_tree.set_species(species[0].id, False) # save later
            self.log_verbose("  Species match, using update file species: %s" % species[0])
            return (True, plot, plot_tree)

        # if only the collision tree has a species, we're done.
        if not species or species.count() == 0:
            self.log_verbose("  No species info for import record, using %d as base record" % plot_tree.id)
            return (True, plot, plot_tree)

        # in this case, both had a species. we should check to see if
        # the species are the same.
        if plot_tree.species != species[0]:
            # now that we have a new species, we want to update the
            # collision tree's species and delete all the old status
            # information.
            self.log_verbose("  Species do not match, using update file species: %s" % species[0])
            plot_tree.set_species(species[0].id, False)
            plot_tree.dbh = None
            plot_tree.height = None
            plot_tree.canopy_height = None
            plot_tree.condition = None
            plot_tree.canopy_condition = None
        return (True, plot, plot_tree) 
    
    def handle_row(self, row):
        self.log_verbose(row)

        # check the physical location
        ok, x, y = self.check_coords(row)
        if not ok: return

        plot = Plot()

        try:
            if self.base_srid != 4326:
                geom = Point(x, y, srid=self.base_srid)
                geom.transform(self.tf)
                self.log_verbose(geom)
                plot.geometry = geom
            else:        
                plot.geometry = Point(x, y, srid=4326)
        except:
            self.log_error("ERROR: Geometry failed to transform", row)
            return

        # check the species (if any)
        ok, species = self.check_species(row)
        if not ok: return
        
        # check for tree info, should we create a tree or just a plot
        if species or self.check_tree_info(row):
            tree = Tree(plot=plot)
        else:
            tree = None
        
        if tree and species:
            tree.species = species[0] 

        
        # check the proximity (try to match up with existing trees)
        # this may return a different plot/tree than created just above, 
        # so don't set anything else on either until after this point
        ok, plot, tree = self.check_proximity(plot, tree, species, row)
        if not ok: return

        
        if row.get('ADDRESS') and not plot.address_street:
            plot.address_street = str(row['ADDRESS']).title()
            plot.geocoded_address = str(row['ADDRESS']).title()
        
        if not plot.geocoded_address: 
            plot.geocoded_address = ""

        # FIXME: get this from the config?
        plot.address_state = 'CA'
        plot.import_event = self.import_event
        plot.last_updated_by = self.updater
        plot.data_owner = self.data_owner
        plot.readonly = self.readonly

        if row.get('PLOTTYPE'):
            for k, v in choices['plot_types']:
                if v == row['PLOTTYPE']:
                    plot.type = k
                    break;

        if row.get('PLOTLENGTH'): 
            plot.length = row['PLOTLENGTH']

        if row.get('PLOTWIDTH'): 
            plot.width = row['PLOTWIDTH']            

        if row.get('ID'):
            plot.owner_orig_id = row['ID']
        
        if row.get('ORIGID'):
            plot.owner_additional_properties = "ORIGID=" + str(row['ORIGID'])

        if row.get('OWNER_ADDITIONAL_PROPERTIES'):
            plot.owner_additional_properties = str(plot.owner_additional_properties) + " " + str(row['OWNER_ADDITIONAL_PROPERTIES'])
        
        if row.get('OWNER_ADDITIONAL_ID'):
            plot.owner_additional_id = str(row['OWNER_ADDITIONAL_ID'])
    
        if row.get('POWERLINE'):
            for k, v in choices['powerlines']:
                if v == row['POWERLINE']:
                    plot.powerline = k
                    break;

        sidewalk_damage = row.get('SIDEWALK')
        if sidewalk_damage is None or sidewalk_damage.strip() == "":
            pass
        elif sidewalk_damage is True or sidewalk_damage.lower() == "true" or sidewalk_damage.lower() == 'yes':
            plot.sidewalk_damage = 2
        else:
            plot.sidewalk_damage = 1

        plot.quick_save()

        pnt = plot.geometry
        n = Neighborhood.objects.filter(geometry__contains=pnt)
        z = ZipCode.objects.filter(geometry__contains=pnt)
        
        plot.neighborhoods = ""
        plot.neighborhood.clear()
        plot.zipcode = None

        if n:
            for nhood in n:
                if nhood:
                    plot.neighborhoods = plot.neighborhoods + " " + nhood.id.__str__()
                    plot.neighborhood.add(nhood)

        if z: plot.zipcode = z[0]

	plot.quick_save()

        if tree:
            tree.plot = plot
            tree.readonly = self.readonly
            tree.import_event = self.import_event
            tree.last_updated_by = self.updater
            
            if row.get('OWNER'):
                tree.tree_owner = str(row["OWNER"])
    
            if row.get('STEWARD'):
                tree.steward_name = str(row["STEWARD"])

            if row.get('SPONSOR'):
                tree.sponsor = str(row["SPONSOR"])

            if row.get('DATEPLANTED'):
                date_string = str(row['DATEPLANTED'])
                try:
                    date = datetime.strptime(date_string, "%m/%d/%Y")
                except:
                    pass
                try:
                    date = datetime.strptime(date_string, "%Y/%m/%d")
                except:
                    pass
                if not date:
                    raise ValueError("Date strings must be in mm/dd/yyyy or yyyy/mm/dd format")
                
                tree.date_planted = date.strftime("%Y-%m-%d")

            if row.get('DIAMETER'):
                tree.dbh = float(row['DIAMETER'])

            if row.get('HEIGHT'):
                tree.height = float(row['HEIGHT'])

            if row.get('CANOPYHEIGHT'):
                tree.canopy_height = float(row['CANOPYHEIGHT'])

            if row.get('CONDITION'):
                for k, v in choices['conditions']:
                    if v == row['CONDITION']:
                        tree.condition = k
                        break;

            if row.get('CANOPYCONDITION'):
                for k, v in choices['canopy_conditions']:
                    if v == row['CANOPYCONDITION']:
                        tree.canopy_condition = k
                        break;

            tree.quick_save()

            if row.get('PROJECT_1'):
                for k, v in Choices().get_field_choices('local'):
                    if v == row['PROJECT_1']:
                        local = TreeFlags(key=k,tree=tree,reported_by=self.updater)
                        local.save()
                        break;
            if row.get('PROJECT_2'):            
                for k, v in Choices().get_field_choices('local'):
                    if v == row['PROJECT_2']:
                        local = TreeFlags(key=k,tree=tree,reported_by=self.updater)
                        local.save()
                        break;
            if row.get('PROJECT_3'):           
                for k, v in Choices().get_field_choices('local'):
                    if v == row['PROJECT_3']:
                        local = TreeFlags(key=k,tree=tree,reported_by=self.updater)
                        local.save()
                        break;

            # rerun validation tests and store results
            tree.validate_all()