tasks.py 7.31 KB
from __future__ import absolute_import
from celery.task import Task
from django.conf import settings
from common.models import *
from utils.Logger import setupLogger
from analyzer.tasks import analysis
from utils.JDManipulator import *
from devices.Telescope import TelescopeController
from devices.CameraNIR import NIRCameraController
from devices.CameraVIS import VISCameraController
import time
import subprocess
import os

'''
    Super class for execute_plan_vis / _nir
'''
class execute_plan(Task):
    def setTelescope(self):
        self.tel = TelescopeController()
        return 0

    def start(self) -> int:
        self.setTelescope()
        self.logger = setupLogger("Observation"+self.type, "Observation"+self.type)
        self.image_count = 0
        # JB TODO REMOVE : is it still useful ?
        # TaskId.objects.filter(task_id=self.request.id).delete()
        if self.countdown > 0:
            time.sleep(self.countdown)
        try:
            self.plan = Plan.objects.get(id=self.plan_id)
            self.duration = julianSecondsToSeconds(self.plan.duration)
        except:
            self.logDB(message="Plan with id %d not found" % (self.plan_id))
            return 1
        self.plan_dir = self.plan.name + "_" + str(self.plan_id)
        self.dir_name = settings.OUTPUT_FOLDER + os.sep + self.plan_dir
        if self.createDirs():
            self.log("Could not create dirs")
            self.logDB(message="Could not create directory " + self.dir_name + " for image storage")
            return 1
        self.launchAnalysis()
        self.log("Starting execution " + self.type)
        return self.logDB('Start plan %s observation from camera %s'%(self.plan.name, str(self.type)))

    def createDirs(self):
        try:
            if not os.path.isdir(settings.OUTPUT_FOLDER):
                os.makedirs(settings.OUTPUT_FOLDER)
            if not os.path.isdir(self.dir_name):
                os.makedirs(self.dir_name)
        except:
            return 1
        return 0

    def log(self, message: str) -> int:
        self.logger.info(self.type + ' -> '+ message)
        return 0

    def logDB(self, message: str) -> int:
        Log.objects.create(agent='Observation manager', message=message)
        return 0

    def launchAnalysis(self):
        analysis.apply_async((self.plan_id, settings.OUTPUT_FOLDER))
        return 0

    def launchCalibration(self) -> int:
        create_calibrations.apply_async((self.plan_id, settings.OUTPUT_FOLDER, self.image_count))
        return 0

    def end(self) -> int:
        self.log("Finished plan observation")
        return self.logDB('Finished plan observation ' + self.plan.name + ' from camera ' + str(self.type))

    def run(self, plan_id: int, countdown: float, type: str) -> int:
        self.plan_id = plan_id
        self.countdown = countdown
        self.type = type
        if self.start():
            self.log("fail exec task -> leaving")
            return 1
        self.execute()
        return self.end()

    def execute(self) -> int:
        time = julianSecondsToSeconds(self.plan.duration)
        self.log("Sleeping for " + str(int(self.duration)))
        time.sleep(int(self.duration))
        return 0

'''
    Gives the orders to the instruments to retrieve the image(s) of a plan VIS.
    Send the images to the calibrator
'''
class execute_plan_vis(execute_plan):
    def setCamera(self):
        self.vis_camera = VISCameraController()
        return 0

    def run(self, plan_id: int, countdown: float) -> int:
        self.setCamera()
        super().run(plan_id, countdown, "VIS")
        return 0

    def execute(self) -> int:
        # TODO All the comunication protocol with the device
        self.tel.do("GOTO " + str(self.plan.position))
        self.vis_camera.do("CAPTURE "+self.dir_name+" "+str(self.plan.nb_images)+" "+str(self.plan.duration))
        self.log("Sleeping for " + str(int(self.duration)))
        time.sleep(int(self.duration))
        self.launchCalibration()
        return 0

'''
    Gives the orders to the instruments to retrieve the image(s) of a plan NIR.
    Send the images to the calibrator
'''
class execute_plan_nir(execute_plan):
    def setCamera(self):
        self.nir_camera = NIRCameraController()
        return 0

    def run(self, plan_id: int, countdown: float) -> int:
        self.setCamera()
        super().run(plan_id, countdown, "NIR")
        return 0

    def execute(self) -> int:
        # TODO All the comunication protocol with the device
        self.tel.do("GOTO " + str(self.plan.position))
        self.nir_camera.do("CAPTURE "+self.dir_name+" "+str(self.plan.nb_images)+" "+str(self.plan.duration))
        self.log("Sleeping for " + str(int(self.duration)))
        time.sleep(int(self.duration))
        self.launchCalibration()
        return 0


'''
    Call a process with a folder and an image number as parameter who will create the
    calibration for an image
'''
class create_calibrations(Task):
    logger = setupLogger("calibrations", "calibrations")

    def log(self, message: str) -> int:
        self.logger.info(message)
        return 0

    def logDB(self, message: str) -> int:
        Log.objects.create(agent='Observation manager', message=message)
        return 0

    def execProcess(self, command: str) -> int:
        self.process = subprocess.Popen(command, shell=True)
        return 0

    def start(self, plan_id: int, folder: str, image_number: int) -> int:
        self.plan_id = plan_id
        self.folder = folder
        self.image_number = image_number
        self.path_dir_file = os.path.dirname(os.path.realpath(__file__))
        try:
            self.plan = Plan.objects.get(id=self.plan_id)
            self.plan_folder = self.plan.name + "_" + str(self.plan_id)
        except:
            self.log("not found calibrations")
            self.logDB(message="Plan with id %d not found"%(self.plan_id))
            return 1
        self.dir_name = self.folder + os.sep + self.plan.name + "_" + str(self.plan_id) + os.sep + "calibrations"
        if self.createDirectory():
            self.log("err dir calibrations")
            self.logDB(message="Could not create folder for calibrations")
            return 1
        self.log("start calibrations")
        return self.logDB("Starting calibration for image " + str(self.image_number))

    def createDirectory(self):
        try:
            if not os.path.isdir(self.dir_name):
                os.makedirs(self.dir_name)
        except:
            return 1
        return 0

    def changeDirectory(self, path: str):
        os.chdir(path)
        return 0

    def execute(self) -> int:
        self.changeDirectory(self.path_dir_file)
        return self.execProcess("./calibrator '"+str(self.folder)+"' '"+self.plan_folder+"' '"+str(self.image_number) + "'")

    def end(self) -> int:
        self.process.wait()
        if self.process.returncode == 0:
            self.log("executed calibrations")
            self.logDB(message="Calibration executed successfully for image " + str(self.image_number))
        else:
            self.log("failed calibrations")
            self.logDB(message="Could not calibrate image " + str(self.image_number))
        return self.process.returncode

    def run(self, plan_id: int, folder: str, image_number: int) -> int:
        if self.start(plan_id, folder, image_number):
            return 1
        self.execute()
        return self.end()