Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ dependencies = [
"pyOSC3@git+https://github.com/glopesdev/pyosc3.git@master",
"newscale@git+https://github.com/AllenNeuralDynamics/python-newscale@axes-on-target",
"aind-auto-train@git+https://github.com/AllenNeuralDynamics/aind-foraging-behavior-bonsai-automatic-training.git@main",
"aind-slims-api@git+https://github.com/AllenNeuralDynamics/aind-slims-api@main",
"aind-dynamic-foraging-models >= 0.12.2",
"aind-dynamic-foraging-basic-analysis >= 0.3.34",
"aind-behavior-services >=0.8, <0.9",
Expand Down
152 changes: 37 additions & 115 deletions src/foraging_gui/Foraging.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
from aind_auto_train.schema.task import TrainingStage
from aind_behavior_services.session import AindBehaviorSessionModel
from aind_data_schema.core.session import Session
from aind_slims_api import SlimsClient, models
from matplotlib.backends.backend_qt5agg import (
NavigationToolbar2QT as NavigationToolbar,
)
Expand Down Expand Up @@ -238,9 +237,6 @@ def __init__(self, parent=None, box_number=1, start_bonsai_ide=True):
# Connect to Bonsai
self._InitializeBonsai()

# connect to Slims
self._ConnectSlims()

# Set up threads
self.threadpool = QThreadPool() # get animal response
self.threadpool2 = QThreadPool() # get animal lick
Expand Down Expand Up @@ -1966,6 +1962,7 @@ def _GetSettings(self):
"clear_figure_after_save": True,
"add_default_project_name": True,
"check_schedule": False,
"waterlog_exe_path": "C://Program Files/AIBS_MPE/waterlog/waterlog.exe",
}

# Try to load the ForagingSettings.json file
Expand Down Expand Up @@ -2097,71 +2094,8 @@ def _GetSettings(self):
]
self.rig_name = "{}".format(self.current_box)

def _ConnectSlims(self):
"""
Connect to Slims
"""
try:
logging.info("Attempting to connect to Slims")
self.slims_client = SlimsClient(
username=os.environ["SLIMS_USERNAME"],
password=os.environ["SLIMS_PASSWORD"],
)
except KeyError as e:
raise KeyError(
"SLIMS_USERNAME and SLIMS_PASSWORD do not exist as "
f"environment variables on machine. Please add. {e}"
)

try:
self.slims_client.fetch_model(
models.SlimsMouseContent, barcode="00000000"
)
except Exception as e:
if "Status 401 – Unauthorized" in str(
e
): # catch error if username and password are incorrect
raise Exception(
f"Exception trying to read from Slims: {e}.\n"
f" Please check credentials:\n"
f"Username: {os.environ['SLIMS_USERNAME']}\n"
f"Password: {os.environ['SLIMS_PASSWORD']}"
)
elif "No record found" not in str(
e
): # bypass if mouse doesn't exist
raise Exception(f"Exception trying to read from Slims: {e}.\n")
logging.info("Successfully connected to Slims")

def _AddWaterLogResult(self, session: Session):
"""
Add WaterLogResult to slims based on current state of gui

:param session: Session object to pull water information from

"""

try: # try and find mouse
logging.info(
f"Attempting to fetch mouse {session.subject_id} from Slims"
)
mouse = self.slims_client.fetch_model(
models.SlimsMouseContent, barcode=session.subject_id
)
except Exception as e:
if "No record found" in str(
e
): # if no mouse found or validation errors on mouse
logging.warning(
f'"No record found" error while trying to fetch mouse {session.subject_id}. '
f"Will not log water."
)
return
else:
logging.error(
f"While fetching mouse {session.subject_id} model, unexpected error occurred: {e}"
)
raise e
def _AddWaterlogResult(self, session: Session):
"""Send weight/water information to databases via waterlog app cli"""

# extract water information
logging.info("Extracting water information from first stimulus epoch")
Expand All @@ -2171,53 +2105,41 @@ def _AddWaterLogResult(self, session: Session):
for k, v in water_json
}

# extract software information
# extract software information to send to waterlog once it can accept it
logging.info("Extracting software information from first data stream")
software = session.stimulus_epochs[0].software[0]
# Access sw name/version with (software.url, software.version)

waterlog_args = [
self.Settings['waterlog_exe_path'],
'--username',
self.behavior_session_model.experimenter[0],
'--mouse-id',
session.subject_id,
'--mouse-weight',
session.animal_weight_post,
'--comment',
session.notes,
'--earned-water',
water["water_in_session_total"],
'--water-supplement-ml',
water["water_after_session"],
'--water-supplement-delivered',
]

# create model
logging.info(
"Creating SlimsWaterlogResult based on session information."
)
print(water)
model = models.SlimsWaterlogResult(
mouse_pk=mouse.pk,
date=datetime.now(),
weight_g=session.animal_weight_post,
operator=self.behavior_session_model.experimenter[0],
water_earned_ml=water["water_in_session_total"],
water_supplement_delivered_ml=water["water_after_session"],
water_supplement_recommended_ml=None,
total_water_ml=water["water_in_session_total"]+water["water_after_session"],
comments=session.notes,
workstation=session.rig_id,
sw_source=software.url,
sw_version=software.version,
test_pk=self.slims_client.fetch_pk(
"Test", test_name="test_waterlog"
),
)
logging.info("Sending water info to waterlog")
process = subprocess.run([str(arg) for arg in waterlog_args])

# check if mouse already has waterlog for at session time and if, so update model
logging.info(
f"Fetching previous waterlog for mouse {session.subject_id}"
)
waterlog = self.slims_client.fetch_models(
models.SlimsWaterlogResult, mouse_pk=mouse.pk, start=0, end=1
)
if waterlog != [] and waterlog[0].date.strftime(
"%Y-%m-%d %H:%M:%S"
) == session.session_start_time.astimezone(timezone.utc).strftime(
"%Y-%m-%d %H:%M:%S"
):
logging.info(
"Waterlog information already exists for this session. Updating waterlog in Slims."
)
model.pk = waterlog[0].pk
self.slims_client.update_model(model=model)
else:
logging.info("Adding waterlog to Slims.")
self.slims_client.add_model(model)
QMessageBox.information(self, "Waterlog", "Go to waterlog app to submit water information.")

Comment thread
patricklatimer marked this conversation as resolved.
try:
process.check_returncode()
except Exception:
logging.warning(
f"Waterlog data for mouse {self.behavior_session_model.subject} cannot be sent to waterlog exe"
f", message: {process.stdout}, {process.stderr}",
exc_info=True,
)

def _InitializeBonsai(self):
"""
Expand Down Expand Up @@ -4171,7 +4093,7 @@ def _Save(self, ForceSave=0, SaveAs=0, SaveContinue=0, BackupSave=0):
# save random reward parameters
Obj['random_reward_par']=self.RandomReward_dialog.random_reward_par

# generate the metadata file and update slims
# generate the metadata file and update waterlog
try:
# save the metadata collected in the metadata dialogue
self.Metadata_dialog._save_metadata_dialog_parameters()
Expand Down Expand Up @@ -4220,10 +4142,10 @@ def _Save(self, ForceSave=0, SaveAs=0, SaveContinue=0, BackupSave=0):
):
self._AddWaterLogResult(session)
elif self.BaseWeight.text() == "" or self.WeightAfter.text() == "":
logging.warning(f"Waterlog for mouse {self.behavior_session_model.subject} cannot be added to slims"
logging.warning(f"Waterlog for mouse {self.behavior_session_model.subject} cannot be added to database"
f" due do unrecorded weight information.")
elif session is None:
logging.warning(f"Waterlog for mouse {self.behavior_session_model.subject} cannot be added to slims"
logging.warning(f"Waterlog for mouse {self.behavior_session_model.subject} cannot be added to database"
f" due do metadata generation failure.")
except Exception as e:
logging.warning(
Expand Down