Unverified Commit 4f971be3 authored by Lauren Adoram-Kershner's avatar Lauren Adoram-Kershner Committed by GitHub
Browse files

Adding reapply() and update_measure_from_jigsaw() function (#479)

* initial commit

* addressing comments

* removing reapply function
parent 56cff627
Loading
Loading
Loading
Loading
+34 −23
Original line number Diff line number Diff line
@@ -1527,7 +1527,7 @@ class NetworkCandidateGraph(CandidateGraph):
            assert len(res) == self.queue_length
        return len(res)

    def apply(self, function, on='edge', args=(), walltime='01:00:00', chunksize=1000, arraychunk=25, filters={}, query_string='', **kwargs):
    def apply(self, function, on='edge', args=(), walltime='01:00:00', chunksize=1000, arraychunk=25, filters={}, query_string='', reapply=False, **kwargs):
        """
        A mirror of the apply function from the standard CandidateGraph object. This implementation
        dispatches the job to the cluster as an independent operation instead of applying an arbitrary function
@@ -1575,6 +1575,9 @@ class NetworkCandidateGraph(CandidateGraph):
                       This is usable only when applying to measures, points, or overlays.
                       The query_string can not be used with a filter and is appropriate for
                       any queries.
        reapply : bool
                  Flag indicating whether you want to resubmit jobs that are still on the queue
                  after an initial apply due to an slurm launching errors.

        kwargs : dict
                 Of keyword arguments passed to the function being applied
@@ -1602,6 +1605,9 @@ class NetworkCandidateGraph(CandidateGraph):
            on='overlaps', distribute_points_kwargs=distribute_points_kwargs)
        """

        job_counter = self.queue_length()

        if not reapply:
            # Determine which obj will be called
            onobj = self.apply_iterable_options[on]
            res = []
@@ -1726,7 +1732,7 @@ class NetworkCandidateGraph(CandidateGraph):
        cnet.to_isis(df, path, targetname=target)
        cnet.write_filelist(fpaths, path=flistpath)

    def update_from_jigsaw(self,path):
    def update_from_jigsaw(self, path, k=10):
        """
        Updates the measures table in the database with data from
        a jigsaw bundle adjust
@@ -1735,6 +1741,9 @@ class NetworkCandidateGraph(CandidateGraph):
        ----------
        path : str
               Full path to a bundle adjusted isis control network

        k    : int
               Number of queries to split the update over
        """
        # Ingest isis control net as a df and do some massaging
        data = cnet.from_isis(path)
@@ -1742,16 +1751,18 @@ class NetworkCandidateGraph(CandidateGraph):
        data_to_update.loc[:,'adjustedCovar'] = data_to_update['adjustedCovar'].apply(lambda row : list(row))
        data_to_update.loc[:,'id'] = data_to_update['id'].apply(lambda row : int(row))

        split_data = np.array_split(data_to_update, k)
        for i, sdf in enumerate(split_data):
            # Generate a temp table, update the real table, then drop the temp table
        data_to_update.to_sql('temp_measures', self.engine, if_exists='replace', index_label='serialnumber', index = False)
            sdf.to_sql(f'temp_measures_{i}', self.engine, if_exists='replace', index_label='serialnumber', index = False)

        sql = """
            sql = f"""
            UPDATE measures AS f
            SET "measureJigsawRejected" = t."measureJigsawRejected", sampler = t."sampleResidual", liner = t."lineResidual", samplesigma = t."samplesigma", linesigma = t."linesigma", apriorisample = t."apriorisample", aprioriline = t."aprioriline"
        FROM temp_measures AS t
            FROM temp_measures_{i} AS t
            WHERE f.serialnumber = t.serialnumber AND f.pointid = t.id;

        DROP TABLE temp_measures;
            DROP TABLE temp_measures_{i};
            """

            with self.session_scope() as session:
+60 −0
Original line number Diff line number Diff line
import pandas as pd
import numpy as np
import shapely.wkb as swkb
from plio.io import io_controlnetwork as cnet
from autocnet.io.db.model import Measures


def db_to_df(engine, sql = """
@@ -85,3 +88,60 @@ ORDER BY measures."pointid", measures."id";
                df.iloc[i] = row

        return df


def update_measure_from_jigsaw(point, path, ncg=None, **kwargs):
    """
    Updates the database (associated with ncg) with a single measure's
    jigsaw line and sample residuals.

    Parameters
    ----------
    point   : obj
              point identifying object as defined by autocnet.io.db.model.Points

    path    : str
              absolute path and network name of control network used to update the measure/database.

    ncg     : obj
              the network candidate graph associated with the measure/database
              being updated.
    """

    if not ncg.Session:
        BrokenPipeError('This function requires a database session from a NetworkCandidateGraph.')

    data = cnet.from_isis(path)
    data_to_update = data[['id', 'serialnumber', 'measureJigsawRejected', 'sampleResidual', 'lineResidual', 'samplesigma', 'linesigma', 'adjustedCovar', 'apriorisample', 'aprioriline']]
    data_to_update.loc[:,'adjustedCovar'] = data_to_update['adjustedCovar'].apply(lambda row : list(row))
    data_to_update.loc[:,'id'] = data_to_update['id'].apply(lambda row : int(row))

    res = data_to_update[(data_to_update['id']==point.id)]
    if res.empty:
        print(f'Point {point.id} does not exist in input network.')
        return

    # update
    resultlog = []
    with ncg.session_scope() as session:
        for row in res.iterrows():
            row = row[1]
            currentlog = {'measure':row["serialnumber"],
                          'status':''}

            residual = np.linalg.norm([row["sampleResidual"], row["lineResidual"]])
            session.query(Measures).\
                    filter(Measures.pointid==point.id, Measures.serial==row["serialnumber"]).\
                    update({"jigreject": row["measureJigsawRejected"],
                        "sampler": row["sampleResidual"],
                        "liner": row["lineResidual"],
                        "residual": residual,
                        "samplesigma": row["samplesigma"],
                        "linesigma": row["linesigma"],
                        "apriorisample": row["apriorisample"],
                        "aprioriline": row["aprioriline"]})
            currentlog['status'] = 'success'
            resultlog.append(currentlog)

        session.commit()
    return resultlog
+1 −0
Original line number Diff line number Diff line
@@ -379,6 +379,7 @@ class Measures(BaseMixin, Base):
    aprioriline = Column(Float)
    sampler = Column(Float)  # Sample Residual
    liner = Column(Float)  # Line Residual
    residual = Column(Float)
    jigreject = Column("measureJigsawRejected", Boolean, default=False)  # jigsaw rejected
    samplesigma = Column(Float)
    linesigma = Column(Float)
+2 −1
Original line number Diff line number Diff line
@@ -784,6 +784,7 @@ def subpixel_register_measure(measureid,
def subpixel_register_point(pointid,
                            iterative_phase_kwargs={},
                            subpixel_template_kwargs={},
                            size_x=100, size_y=100,
                            cost_func=lambda x,y: 1/x**2 * y,
                            threshold=0.005,
                            ncg=None,
@@ -858,7 +859,7 @@ def subpixel_register_point(pointid,
                                                        source.sample, source.line,
                                                        template_kwargs=subpixel_template_kwargs,
                                                        phase_kwargs=iterative_phase_kwargs,
                                                        size_x=100, size_y=100)
                                                        size_x=size_y, size_y=size_x)
            except Exception as e:
                print(f'geom_match failed on measure {measure.id} with exception -> {e}')
                measure.ignore = True