def update_wm5_catch_weights(self): """ Go to DB directly and find catches w. WM5. Update catch_weight with OTC-RET., then EMIT to signal QML func lives here so it can interact with both _hauls and _catches signals NOTE: catch_weight cant be negative in DB, so if negative set to null / None :return: None """ if self.isFixedGear: # wm5 doesn't exist w. FG return wm5_catches = Catches.select(Catches.catch, Catches.catch_num).where( (Catches.fishing_activity == self._hauls.currentHaulDBId) & (Catches.catch_weight_method == '5') ).execute() new_wt = self._hauls.getData('observer_total_catch') - self._hauls.retainedHaulWeight new_wt = new_wt if new_wt > 0 else None # wt can't be negative in DB, set to None/Null for c in wm5_catches: # there shouldn't be more than one, but just in case Catches.update(catch_weight=new_wt).where( (Catches.catch == c.catch) ).execute() logging.info(f"CatchNum {c.catch_num} (ID: {c.catch}) WM5 weight updated to {new_wt}") self.wm5WeightChanged.emit(c.catch, new_wt) # tell CC QML page to update too
def add_vessel_ret(self, haul_id, vessel_ret): """ Add a vessel retained ListElement to our model and save to DB @param haul_id: Haul DB Id (Fishing Activity) @param vessel_ret: ListElement QJSValue @return: """ if isinstance(vessel_ret, QJSValue): # convert QJSValue to QVariant (then to dict) vessel_ret = vessel_ret.toVariant() found_cc_code = CatchCategories.get( CatchCategories.catch_category_code == vessel_ret['cc_code']) catch_num = ObserverCatches.get_next_catch_num_for_this_haul( haul_id, self._logger) Catches.create( fishing_activity=haul_id, catch_category=found_cc_code.catch_category, catch_weight=vessel_ret['weight'], catch_weight_method='7', catch_purity=None, catch_weight_um='LB', catch_disposition='R', catch_num=catch_num, created_by=ObserverDBUtil.get_current_user_id(), created_date=ObserverDBUtil.get_arrow_datestr(), ) self.appendItem(vessel_ret)
def load_observer_retained(self, fishing_activity_id, is_fixed_gear=False): """ Load catches from database :return: list of catch codes (strings) """ observer_retained_catches_query = Catches.select().where( (Catches.fishing_activity == fishing_activity_id) & (Catches.catch_disposition == 'R') & ~((Catches.catch_weight_method.is_null(False)) & (Catches.catch_weight_method == '7'))) ret_catches = observer_retained_catches_query.count() catch_codes = list() self.clear() if ret_catches > 0: for c in observer_retained_catches_query: if is_fixed_gear: self.appendItem({ 'cc_code': c.catch_category.catch_category_code, 'weight': c.sample_weight }) else: self.appendItem({ 'cc_code': c.catch_category.catch_category_code, 'weight': c.catch_weight }) return catch_codes
def _calculate_retained_spp_avg(self, species_ids): """ FIELD-1900: Used to auto-calc DR12/15 weights Separate function to store retained average calculation Take all retained baskets with counts and weights for species id param and get avg fish wt :param species_ids: int[], list of species_ids for a given species_complex :return: float """ if self._current_set: faid = self._current_set.fishing_activity avg = Catches.select( (fn.sum(SpeciesCompositionBaskets.basket_weight_itq) / fn.sum(SpeciesCompositionBaskets.fish_number_itq)) ).join(SpeciesCompositions).join(SpeciesCompositionItems).join( SpeciesCompositionBaskets ).where( (Catches.fishing_activity == faid) & # haul (Catches.catch_disposition == 'R') & # retained (SpeciesCompositionBaskets.basket_weight_itq.is_null(False)) & # baskets with actual weights (SpeciesCompositionBaskets.fish_number_itq.is_null(False)) & # baskets with actual counts (SpeciesCompositionItems.species.in_(species_ids) ) # species associated with CC ).scalar() # DO NOT ROUND HERE # avg = ObserverDBUtil.round_up(avg) # round here, precision will propagate to downstream vals self._logger.info( f"Retained avg for set {faid}, species_ids {species_ids} = {avg}" ) return avg
def _recalculate_catches_hooks_sampled(self, set_rec, avg_hook_count): catches_q = Catches.select().where( Catches.fishing_activity == set_rec.fishing_activity) for c in catches_q: if avg_hook_count and c.gear_segments_sampled: old_hooks = c.hooks_sampled new_hooks = round(avg_hook_count * c.gear_segments_sampled) self._logger.info( f'Catch {c.catch} Hooks sampled {old_hooks} -> {new_hooks}' ) c.hooks_sampled = new_hooks c.save()
def _get_catch_models(self, fishing_activity_id): """ Load catch table models for a given haul from DB. :param fishing_activity_id: haul ID :return: list of catch ORM models """ if fishing_activity_id is None: self._logger.error('Activity ID none') return catch_category_q = Catches.select(). \ where(Catches.fishing_activity == fishing_activity_id). \ order_by(Catches.catch_num) return catch_category_q
def check_haul_empty(self, haul_id): """ Queries DB to see if there are data records associated with a haul @param haul_id: DBID @return: True if haul is empty and can be deleted, False otherwise """ if not haul_id: self._logger.warning('Invalid haul ID passed to check_haul_empty.') return False catches_q = Catches.select().where(Catches.fishing_activity == haul_id) if len(catches_q) > 0: self._logger.debug('Haul {} is not empty, has {} catches associated.'.format(haul_id, len(catches_q))) return False return True
def _recalculate_catches_hooks_sampled(self, set_rec, avg_hook_count): catches_q = Catches.select().where( Catches.fishing_activity == set_rec.fishing_activity) for c in catches_q: if avg_hook_count and c.gear_segments_sampled: old_hooks = c.hooks_sampled new_hooks = round(avg_hook_count * c.gear_segments_sampled) new_hooks_unrounded = avg_hook_count * c.gear_segments_sampled self._logger.info( f'Catch {c.catch} Hooks sampled {old_hooks} -> {new_hooks} (unrounded = {new_hooks_unrounded})' ) c.hooks_sampled = new_hooks c.hooks_sampled_unrounded = new_hooks_unrounded # FIELD-2102: this is the val used for OTC recalc c.save()
def load_vessel_retained(self, fishing_activity_id): """ Load catches from database :return: list of catch codes (strings) """ vessel_retained_catches_query = Catches.select().where( (Catches.fishing_activity == fishing_activity_id) & (Catches.catch_disposition == 'R') & (Catches.catch_weight_method == '7')) v_ret_catches = vessel_retained_catches_query.count() catch_codes = list() self.clear() if v_ret_catches > 0: for c in vessel_retained_catches_query: self.appendItem({ 'cc_code': c.catch_category.catch_category_code, 'weight': c.catch_weight }) return catch_codes
def _sum_catch_weight(self, catch_id): """ Sum underlying species_comp_item.species_weight values and update Catch.sample_weight Used to refresh values after underlying basket updates, post-set :param catch_id: catch DB id (int) :return: None """ try: catch = Catches.get(Catches.catch == catch_id) except Catches.DoesNotExist as e: self._logger.error(f"Unable to find catch {catch_id} in DB") return new_wt = SpeciesCompositionItems.select( fn.sum(SpeciesCompositionItems.species_weight)).join( SpeciesCompositions).where( SpeciesCompositions.catch == catch_id).scalar() if catch.sample_weight != new_wt: catch.sample_weight = new_wt catch.save() self._logger.info( f"Catch {catch_id} sample_weight updated to {new_wt}")