Esempio n. 1
0
    def test_1(self):
        pj = json.loads(open("files/test2.boris").read())
        r = utilities.convert_time_to_decimal(pj)

        txt = open("files/test.txt").read()
        pj_dec = eval(txt)
        assert r == pj_dec
Esempio n. 2
0
    def test_1(self):
        pj = json.loads(open("files/test2.boris").read())
        r = utilities.convert_time_to_decimal(pj)

        txt = open("files/test.txt").read()
        pj_dec = eval(txt)
        assert r == pj_dec
Esempio n. 3
0
 def test_t8(self):
     pj_float = json.loads(open("files/test.boris").read())
     pj = utilities.convert_time_to_decimal(pj_float)
     r = utilities.get_current_states_modifiers_by_subject(state_behaviors_codes=["s"],
                                             events=pj["observations"]["observation #1"]["events"],
                                             subjects=pj["subjects_conf"],
                                             time=Decimal("8.0"),
                                             include_modifiers=False)
     assert r == {'0': [], '1': []}
Esempio n. 4
0
 def test_events(self):
     pj_float = json.loads(open("files/test.boris").read())
     pj = utilities.convert_time_to_decimal(pj_float)
     r = utilities.get_current_points_by_subject(point_behaviors_codes=["p"],
                               events=pj["observations"]["offset positif"]["events"],
                               subjects={"0":{"key":"", "name": "", "description":"no focal subject"}},
                               time=Decimal("22.6"),
                               tolerance=Decimal("1"))
     assert r == {'0': [['p', '']]}
Esempio n. 5
0
 def test_t8(self):
     pj_float = json.loads(open("files/test.boris").read())
     pj = utilities.convert_time_to_decimal(pj_float)
     r = utilities.get_current_states_modifiers_by_subject(state_behaviors_codes=["s"],
                                             events=pj["observations"]["observation #1"]["events"],
                                             subjects=pj["subjects_conf"],
                                             time=Decimal("8.0"),
                                             include_modifiers=False)
     assert r == {'0': [], '1': []}
Esempio n. 6
0
 def test_events(self):
     pj_float = json.loads(open("files/test.boris").read())
     pj = utilities.convert_time_to_decimal(pj_float)
     r = utilities.get_current_points_by_subject(point_behaviors_codes=["p"],
                               events=pj["observations"]["offset positif"]["events"],
                               subjects={"0":{"key":"", "name": "", "description":"no focal subject"}},
                               time=Decimal("22.6"),
                               tolerance=Decimal("1"))
     assert r == {'0': [['p', '']]}
Esempio n. 7
0
 def test_events_with_modifiers_required(self):
     pj_float = json.loads(open("files/test.boris").read())
     pj = utilities.convert_time_to_decimal(pj_float)
     r = utilities.get_current_states_modifiers_by_subject(state_behaviors_codes=["r", "s"],
                                             events=pj["observations"]["modifiers"]["events"],
                                             subjects={"0":{"key":"", "name": "", "description":"no focal subject"}},
                                             time=Decimal("20"),
                                             include_modifiers=True)
     #print(r)
     assert r == {'0': ['r (m1)']}
Esempio n. 8
0
 def test_events_with_modifiers_required(self):
     pj_float = json.loads(open("files/test.boris").read())
     pj = utilities.convert_time_to_decimal(pj_float)
     r = utilities.get_current_states_modifiers_by_subject(state_behaviors_codes=["r", "s"],
                                             events=pj["observations"]["modifiers"]["events"],
                                             subjects={"0":{"key":"", "name": "", "description":"no focal subject"}},
                                             time=Decimal("20"),
                                             include_modifiers=True)
     #print(r)
     assert r == {'0': ['r (m1)']}
Esempio n. 9
0
 def test_events_without_modifiers2(self):
     pj_float = json.loads(open("files/test.boris").read())
     pj = utilities.convert_time_to_decimal(pj_float)
     r = utilities.get_current_points_by_subject(point_behaviors_codes=["p"],
                               events=pj[config.OBSERVATIONS]["modifiers"]["events"],
                               subjects={"0":{"key":"", "name": "", "description":"no focal subject"}},
                               time=Decimal("8.000"),
                               tolerance=Decimal("5"),
                               include_modifiers=True)
     assert r == {'0': []}
Esempio n. 10
0
 def test_events_with_modifiers3(self):
     # no events should correspond to selected behavior
     pj_float = json.loads(open("files/test.boris").read())
     pj = utilities.convert_time_to_decimal(pj_float)
     r = utilities.get_current_points_by_subject(point_behaviors_codes=["q"],
                               events=pj[config.OBSERVATIONS]["modifiers"][config.EVENTS],
                               subjects={"0":{"key":"", "name": "", "description":"no focal subject"}},
                               time=Decimal("8.000"),
                               tolerance=Decimal("5"),
                               include_modifiers=True)
     assert r == {'0': [('q', 'm1'), ('q', 'm2')]}
Esempio n. 11
0
def open_project_json(projectFileName):
    """
    open project json

    Args:
        projectFileName (str): path of project

    Returns:
        str: project path
        bool: True if project changed
        dict: BORIS project
        str: message
    """

    logging.debug("open project: {0}".format(projectFileName))

    projectChanged = False
    msg = ""

    if not os.path.isfile(projectFileName):
        return projectFileName, projectChanged, {
            "error": "File {} not found".format(projectFileName)
        }, msg

    try:
        s = open(projectFileName, "r").read()
    except PermissionError:
        return projectFileName, projectChanged, {
            "error": "File {}: Permission denied".format(projectFileName)
        }, msg
    except Exception:
        return projectFileName, projectChanged, {
            "error":
            "Error on file {}: {}".format(projectFileName,
                                          sys.exc_info()[1])
        }, msg

    try:
        pj = json.loads(s)
    except json.decoder.JSONDecodeError:
        return projectFileName, projectChanged, {
            "error": "This project file seems corrupted"
        }, msg
    except Exception:
        return projectFileName, projectChanged, {
            "error":
            "This project file seems corruptedError on file {}: {}".format(
                projectFileName,
                sys.exc_info()[1])
        }, msg

    # transform time to decimal
    pj = utilities.convert_time_to_decimal(pj)

    # add coding_map key to old project files
    if "coding_map" not in pj:
        pj["coding_map"] = {}
        projectChanged = True

    # add subject description
    if "project_format_version" in pj:
        for idx in [x for x in pj[SUBJECTS]]:
            if "description" not in pj[SUBJECTS][idx]:
                pj[SUBJECTS][idx]["description"] = ""
                projectChanged = True

    # check if project file version is newer than current BORIS project file version
    if "project_format_version" in pj and Decimal(
            pj["project_format_version"]) > Decimal(project_format_version):
        return (
            projectFileName,
            projectChanged,
            {
                "error":
                ("This project file was created with a more recent version of BORIS.<br>"
                 "You must update BORIS to <b>v. >= {}</b> to open this project"
                 ).format(pj["project_format_version"])
            },
            msg,
        )

    # check if old version  v. 0 *.obs
    if "project_format_version" not in pj:

        # convert VIDEO, AUDIO -> MEDIA
        pj["project_format_version"] = project_format_version
        projectChanged = True

        for obs in [x for x in pj[OBSERVATIONS]]:

            # remove 'replace audio' key
            if "replace audio" in pj[OBSERVATIONS][obs]:
                del pj[OBSERVATIONS][obs]["replace audio"]

            if pj[OBSERVATIONS][obs][TYPE] in ["VIDEO", "AUDIO"]:
                pj[OBSERVATIONS][obs][TYPE] = MEDIA

            # convert old media list in new one
            if len(pj[OBSERVATIONS][obs][FILE]):
                d1 = {PLAYER1: [pj[OBSERVATIONS][obs][FILE][0]]}

            if len(pj[OBSERVATIONS][obs][FILE]) == 2:
                d1[PLAYER2] = [pj[OBSERVATIONS][obs][FILE][1]]

            pj[OBSERVATIONS][obs][FILE] = d1

        # convert VIDEO, AUDIO -> MEDIA
        for idx in [x for x in pj[SUBJECTS]]:
            key, name = pj[SUBJECTS][idx]
            pj[SUBJECTS][idx] = {"key": key, "name": name, "description": ""}

        msg = (
            "The project file was converted to the new format (v. {}) in use with your version of BORIS.<br>"
            "Choose a new file name for saving it."
        ).format(project_format_version)
        projectFileName = ""

    # update modifiers to JSON format

    # check if project format version < 4 (modifiers were str)
    project_lowerthan4 = False
    if "project_format_version" in pj and utilities.versiontuple(
            pj["project_format_version"]) < utilities.versiontuple("4.0"):
        for idx in pj[ETHOGRAM]:
            if pj[ETHOGRAM][idx]["modifiers"]:
                if isinstance(pj[ETHOGRAM][idx]["modifiers"], str):
                    project_lowerthan4 = True
                    modif_set_list = pj[ETHOGRAM][idx]["modifiers"].split("|")
                    modif_set_dict = {}
                    for modif_set in modif_set_list:
                        modif_set_dict[str(len(modif_set_dict))] = {
                            "name": "",
                            "type": SINGLE_SELECTION,
                            "values": modif_set.split(",")
                        }
                    pj[ETHOGRAM][idx]["modifiers"] = dict(modif_set_dict)
            else:
                pj[ETHOGRAM][idx]["modifiers"] = {}

        if not project_lowerthan4:
            msg = "The project version was updated from {} to {}".format(
                pj["project_format_version"], project_format_version)
            pj["project_format_version"] = project_format_version
            projectChanged = True

    # add category key if not found
    for idx in pj[ETHOGRAM]:
        if "category" not in pj[ETHOGRAM][idx]:
            pj[ETHOGRAM][idx]["category"] = ""

    # if one file is present in player #1 -> set "media_info" key with value of media_file_info
    for obs in pj[OBSERVATIONS]:
        if pj[OBSERVATIONS][obs][TYPE] in [
                MEDIA
        ] and MEDIA_INFO not in pj[OBSERVATIONS][obs]:
            pj[OBSERVATIONS][obs][MEDIA_INFO] = {
                LENGTH: {},
                "fps": {},
                "hasVideo": {},
                "hasAudio": {}
            }
            for player in [PLAYER1, PLAYER2]:
                # fix bug Anne Maijer 2017-07-17
                if pj[OBSERVATIONS][obs][FILE] == []:
                    pj[OBSERVATIONS][obs][FILE] = {"1": [], "2": []}

                for media_file_path in pj[OBSERVATIONS][obs]["file"][player]:
                    # FIX: ffmpeg path
                    ret, msg = utilities.check_ffmpeg_path()
                    if not ret:
                        return projectFileName, projectChanged, {
                            "error": "FFmpeg path not found"
                        }, ""
                    else:
                        ffmpeg_bin = msg

                    r = utilities.accurate_media_analysis(
                        ffmpeg_bin, media_file_path)

                    if "duration" in r and r["duration"]:
                        pj[OBSERVATIONS][obs][MEDIA_INFO][LENGTH][
                            media_file_path] = float(r["duration"])
                        pj[OBSERVATIONS][obs][MEDIA_INFO][FPS][
                            media_file_path] = float(r["fps"])
                        pj[OBSERVATIONS][obs][MEDIA_INFO]["hasVideo"][
                            media_file_path] = r["has_video"]
                        pj[OBSERVATIONS][obs][MEDIA_INFO]["hasAudio"][
                            media_file_path] = r["has_audio"]
                        project_updated, projectChanged = True, True
                    else:  # file path not found
                        if ("media_file_info" in pj[OBSERVATIONS][obs] and len(
                                pj[OBSERVATIONS][obs]["media_file_info"]) == 1
                                and len(
                                    pj[OBSERVATIONS][obs][FILE][PLAYER1]) == 1
                                and len(pj[OBSERVATIONS][obs][FILE][PLAYER2])
                                == 0):
                            media_md5_key = list(pj[OBSERVATIONS][obs]
                                                 ["media_file_info"].keys())[0]
                            # duration
                            pj[OBSERVATIONS][obs][MEDIA_INFO] = {
                                LENGTH: {
                                    media_file_path:
                                    pj[OBSERVATIONS][obs]["media_file_info"]
                                    [media_md5_key]["video_length"] / 1000
                                }
                            }
                            projectChanged = True

                            # FPS
                            if "nframe" in pj[OBSERVATIONS][obs][
                                    "media_file_info"][media_md5_key]:
                                pj[OBSERVATIONS][obs][MEDIA_INFO][FPS] = {
                                    media_file_path:
                                    pj[OBSERVATIONS][obs]["media_file_info"]
                                    [media_md5_key]["nframe"] /
                                    (pj[OBSERVATIONS][obs]["media_file_info"]
                                     [media_md5_key]["video_length"] / 1000)
                                }
                            else:
                                pj[OBSERVATIONS][obs][MEDIA_INFO][FPS] = {
                                    media_file_path: 0
                                }

    # update project to v.7 for time offset second player
    project_lowerthan7 = False
    for obs in pj[OBSERVATIONS]:
        if "time offset second player" in pj[OBSERVATIONS][obs]:
            if MEDIA_INFO not in pj[OBSERVATIONS][obs]:
                pj[OBSERVATIONS][obs][MEDIA_INFO] = {}
            if "offset" not in pj[OBSERVATIONS][obs][MEDIA_INFO]:
                pj[OBSERVATIONS][obs][MEDIA_INFO]["offset"] = {}
            for player in pj[OBSERVATIONS][obs][FILE]:
                pj[OBSERVATIONS][obs][MEDIA_INFO]["offset"][player] = 0.0
            if pj[OBSERVATIONS][obs]["time offset second player"]:
                pj[OBSERVATIONS][obs][MEDIA_INFO]["offset"]["2"] = float(
                    pj[OBSERVATIONS][obs]["time offset second player"])

            del pj[OBSERVATIONS][obs]["time offset second player"]
            project_lowerthan7 = True

            msg = (
                "The project file was converted to the new format (v. {project_version}) in use with your version of BORIS.<br>"
                "Please note that this new version will NOT be compatible with previous BORIS versions (&lt; v. {project_version}).<br>"
            ).format(project_version=project_format_version)

            projectChanged = True

    if project_lowerthan7:

        msg = (
            "The project was updated to the current project version ({project_format_version})."
        ).format(project_format_version=project_format_version)

        try:
            copyfile(
                projectFileName,
                projectFileName.replace(
                    ".boris",
                    ".v{}.boris".format(pj["project_format_version"])))
            msg += "\n\nThe old file project was saved as {}".format(
                projectFileName.replace(
                    ".boris",
                    ".v{}.boris".format(pj["project_format_version"])))
        except Exception:
            pass

        pj["project_format_version"] = project_format_version

    return projectFileName, projectChanged, pj, msg
Esempio n. 12
0
def open_project_json(projectFileName):
    """
    open project json
    
    Args:
        projectFileName (str): path of project
        
    Returns:
        str: project path
        bool: True if project changed
        dict: BORIS project
        str: message
    """

    logging.debug("open project: {0}".format(projectFileName))

    projectChanged = False
    msg = ""

    if not os.path.isfile(projectFileName):
        return projectFileName, projectChanged, {
            "error": "File {} not found".format(projectFileName)
        }, msg

    s = open(projectFileName, "r").read()

    try:
        pj = json.loads(s)
    except:
        return projectFileName, projectChanged, {
            "error": "This project file seems corrupted"
        }, msg

    # transform time to decimal
    pj = utilities.convert_time_to_decimal(pj)

    # add coding_map key to old project files
    if not "coding_map" in pj:
        pj["coding_map"] = {}
        projectChanged = True

    # add subject description
    if "project_format_version" in pj:
        for idx in [x for x in pj[SUBJECTS]]:
            if not "description" in pj[SUBJECTS][idx]:
                pj[SUBJECTS][idx]["description"] = ""
                projectChanged = True

    # check if project file version is newer than current BORIS project file version
    if "project_format_version" in pj and Decimal(
            pj["project_format_version"]) > Decimal(project_format_version):

        return projectFileName, projectChanged, {
            "error":
            ("This project file was created with a more recent version of BORIS.\n"
             "You must update BORIS to open it")
        }, msg

    # check if old version  v. 0 *.obs
    if "project_format_version" not in pj:

        # convert VIDEO, AUDIO -> MEDIA
        pj['project_format_version'] = project_format_version
        projectChanged = True

        for obs in [x for x in pj[OBSERVATIONS]]:

            # remove 'replace audio' key
            if "replace audio" in pj[OBSERVATIONS][obs]:
                del pj[OBSERVATIONS][obs]['replace audio']

            if pj[OBSERVATIONS][obs][TYPE] in ['VIDEO', 'AUDIO']:
                pj[OBSERVATIONS][obs][TYPE] = MEDIA

            # convert old media list in new one
            if len(pj[OBSERVATIONS][obs][FILE]):
                d1 = {PLAYER1: [pj[OBSERVATIONS][obs][FILE][0]]}

            if len(pj[OBSERVATIONS][obs][FILE]) == 2:
                d1[PLAYER2] = [pj[OBSERVATIONS][obs][FILE][1]]

            pj[OBSERVATIONS][obs][FILE] = d1

        # convert VIDEO, AUDIO -> MEDIA
        for idx in [x for x in pj[SUBJECTS]]:
            key, name = pj[SUBJECTS][idx]
            pj[SUBJECTS][idx] = {"key": key, "name": name, "description": ""}

        msg = (
            "The project file was converted to the new format (v. {}) in use with your version of BORIS.<br>"
            "Choose a new file name for saving it."
        ).format(project_format_version)
        projectFileName = ""

    for obs in pj[OBSERVATIONS]:
        if not "time offset second player" in pj[OBSERVATIONS][obs]:
            pj[OBSERVATIONS][obs]["time offset second player"] = Decimal("0.0")
            projectChanged = True

    # update modifiers to JSON format

    project_lowerthan4 = False

    logging.debug("project_format_version: {}".format(
        utilities.versiontuple(pj["project_format_version"])))

    if "project_format_version" in pj and utilities.versiontuple(
            pj["project_format_version"]) < utilities.versiontuple("4.0"):

        for idx in pj[ETHOGRAM]:
            if pj[ETHOGRAM][idx]["modifiers"]:
                if isinstance(pj[ETHOGRAM][idx]["modifiers"], str):
                    project_lowerthan4 = True
                    modif_set_list = pj[ETHOGRAM][idx]["modifiers"].split("|")
                    modif_set_dict = {}
                    for modif_set in modif_set_list:
                        modif_set_dict[str(len(modif_set_dict))] = {
                            "name": "",
                            "type": SINGLE_SELECTION,
                            "values": modif_set.split(",")
                        }
                    pj[ETHOGRAM][idx]["modifiers"] = dict(modif_set_dict)
            else:
                pj[ETHOGRAM][idx]["modifiers"] = {}

        if not project_lowerthan4:
            msg = "The project version was updated from {} to {}".format(
                pj["project_format_version"], project_format_version)
            pj["project_format_version"] = project_format_version
            projectChanged = True

    # add category key if not found
    for idx in pj[ETHOGRAM]:
        if "category" not in pj[ETHOGRAM][idx]:
            pj[ETHOGRAM][idx]["category"] = ""

    logging.debug("project_lowerthan4: {}".format(project_lowerthan4))

    if project_lowerthan4:

        copyfile(projectFileName,
                 projectFileName.replace(".boris", "_old_version.boris"))

        msg = (
            "The project was updated to the current project version ({project_format_version}).\n\n"
            "The old file project was saved as {project_file_name}").format(
                project_format_version=project_format_version,
                project_file_name=projectFileName.replace(
                    ".boris", "_old_version.boris"))

    # if one file is present in player #1 -> set "media_info" key with value of media_file_info
    project_updated = False

    for obs in pj[OBSERVATIONS]:
        if pj[OBSERVATIONS][obs][TYPE] in [
                MEDIA
        ] and "media_info" not in pj[OBSERVATIONS][obs]:
            pj[OBSERVATIONS][obs]['media_info'] = {
                "length": {},
                "fps": {},
                "hasVideo": {},
                "hasAudio": {}
            }
            for player in [PLAYER1, PLAYER2]:
                # fix bug Anne Maijer 2017-07-17
                if pj[OBSERVATIONS][obs]["file"] == []:
                    pj[OBSERVATIONS][obs]["file"] = {"1": [], "2": []}

                for media_file_path in pj[OBSERVATIONS][obs]["file"][player]:
                    # FIX: ffmpeg path

                    ret, msg = utilities.check_ffmpeg_path()
                    if not ret:
                        return projectFileName, projectChanged, {
                            "error": "FFmpeg path not found"
                        }, ""
                    else:
                        ffmpeg_bin = msg

                    nframe, videoTime, videoDuration, fps, hasVideo, hasAudio = utilities.accurate_media_analysis(
                        ffmpeg_bin, media_file_path)

                    if videoDuration:
                        pj[OBSERVATIONS][obs]['media_info']["length"][
                            media_file_path] = videoDuration
                        pj[OBSERVATIONS][obs]['media_info']["fps"][
                            media_file_path] = fps
                        pj[OBSERVATIONS][obs]['media_info']["hasVideo"][
                            media_file_path] = hasVideo
                        pj[OBSERVATIONS][obs]['media_info']["hasAudio"][
                            media_file_path] = hasAudio
                        project_updated, projectChanged = True, True
                    else:  # file path not found
                        if ("media_file_info" in pj[OBSERVATIONS][obs] and len(
                                pj[OBSERVATIONS][obs]["media_file_info"]) == 1
                                and len(pj[OBSERVATIONS][obs]["file"][PLAYER1])
                                == 1
                                and len(pj[OBSERVATIONS][obs]["file"][PLAYER2])
                                == 0):
                            media_md5_key = list(pj[OBSERVATIONS][obs]
                                                 ["media_file_info"].keys())[0]
                            # duration
                            pj[OBSERVATIONS][obs]["media_info"] = {
                                "length": {
                                    media_file_path:
                                    pj[OBSERVATIONS][obs]["media_file_info"]
                                    [media_md5_key]["video_length"] / 1000
                                }
                            }
                            project_updated, projectChanged = True, True

                            # FPS
                            if "nframe" in pj[OBSERVATIONS][obs][
                                    "media_file_info"][media_md5_key]:
                                pj[OBSERVATIONS][obs]['media_info']['fps'] = {
                                    media_file_path:
                                    pj[OBSERVATIONS][obs]['media_file_info']
                                    [media_md5_key]['nframe'] /
                                    (pj[OBSERVATIONS][obs]['media_file_info']
                                     [media_md5_key]['video_length'] / 1000)
                                }
                            else:
                                pj[OBSERVATIONS][obs]['media_info']['fps'] = {
                                    media_file_path: 0
                                }

    if project_updated:
        msg = "The media files information was updated to the new project format."

    return projectFileName, projectChanged, pj, msg
Esempio n. 13
0
def open_project_json(projectFileName):
    """
    open project json

    Args:
        projectFileName (str): path of project

    Returns:
        str: project path
        bool: True if project changed
        dict: BORIS project
        str: message
    """

    logging.debug("Abrir projeto: {0}".format(projectFileName))

    projectChanged = False
    msg = ""

    if not os.path.isfile(projectFileName):
        return projectFileName, projectChanged, {
            "error": "Arquivo {} não existe".format(projectFileName)
        }, msg

    s = open(projectFileName, "r").read()

    try:
        pj = json.loads(s)
    except:
        return projectFileName, projectChanged, {
            "error": "Este arquivo de projeto parece corrompido"
        }, msg

    # transform time to decimal
    pj = utilities.convert_time_to_decimal(pj)

    # add coding_map key to old project files
    if not "coding_map" in pj:
        pj["coding_map"] = {}
        projectChanged = True

    # add subject description
    if "project_format_version" in pj:
        for idx in [x for x in pj[SUBJECTS]]:
            if not "description" in pj[SUBJECTS][idx]:
                pj[SUBJECTS][idx]["description"] = ""
                projectChanged = True

    # check if project file version is newer than current BORIS project file version
    if "project_format_version" in pj and Decimal(
            pj["project_format_version"]) > Decimal(project_format_version):

        return projectFileName, projectChanged, {
            "error":
            ("Este arquivo de projeto foi criado com uma versão mais recente do BORIS.<br>"
             "Você pode utilizar o BORIS <b>v. >= {}</b> Para abri esse arquivo"
             ).format(pj["project_format_version"])
        }, msg

    # check if old version  v. 0 *.obs
    if "project_format_version" not in pj:

        # convert VIDEO, AUDIO -> MEDIA
        pj['project_format_version'] = project_format_version
        projectChanged = True

        for obs in [x for x in pj[OBSERVATIONS]]:

            # remove 'replace audio' key
            if "replace audio" in pj[OBSERVATIONS][obs]:
                del pj[OBSERVATIONS][obs]['replace audio']

            if pj[OBSERVATIONS][obs][TYPE] in ['VIDEO', 'AUDIO']:
                pj[OBSERVATIONS][obs][TYPE] = MEDIA

            # convert old media list in new one
            if len(pj[OBSERVATIONS][obs][FILE]):
                d1 = {PLAYER1: [pj[OBSERVATIONS][obs][FILE][0]]}

            if len(pj[OBSERVATIONS][obs][FILE]) == 2:
                d1[PLAYER2] = [pj[OBSERVATIONS][obs][FILE][1]]

            pj[OBSERVATIONS][obs][FILE] = d1

        # convert VIDEO, AUDIO -> MEDIA
        for idx in [x for x in pj[SUBJECTS]]:
            key, name = pj[SUBJECTS][idx]
            pj[SUBJECTS][idx] = {"key": key, "name": name, "description": ""}

        msg = (
            "O arquivo de projeto foi convertido para o novo formato (v. {}) Em uso com sua versão do BORIS.<br>"
            "Escolha um novo nome de arquivo para salvá-lo."
        ).format(project_format_version)
        projectFileName = ""

    for obs in pj[OBSERVATIONS]:
        if not "time offset second player" in pj[OBSERVATIONS][obs]:
            pj[OBSERVATIONS][obs]["time offset second player"] = Decimal("0.0")
            projectChanged = True

    # update modifiers to JSON format

    project_lowerthan4 = False

    logging.debug("project_format_version: {}".format(
        utilities.versiontuple(pj["project_format_version"])))

    if "project_format_version" in pj and utilities.versiontuple(
            pj["project_format_version"]) < utilities.versiontuple("4.0"):

        for idx in pj[ETHOGRAM]:
            if pj[ETHOGRAM][idx]["modifiers"]:
                if isinstance(pj[ETHOGRAM][idx]["modifiers"], str):
                    project_lowerthan4 = True
                    modif_set_list = pj[ETHOGRAM][idx]["modifiers"].split("|")
                    modif_set_dict = {}
                    for modif_set in modif_set_list:
                        modif_set_dict[str(len(modif_set_dict))] = {
                            "name": "",
                            "type": SINGLE_SELECTION,
                            "values": modif_set.split(",")
                        }
                    pj[ETHOGRAM][idx]["modifiers"] = dict(modif_set_dict)
            else:
                pj[ETHOGRAM][idx]["modifiers"] = {}

        if not project_lowerthan4:
            msg = "A versão do projeto foi atualizada de {} para {}".format(
                pj["project_format_version"], project_format_version)
            pj["project_format_version"] = project_format_version
            projectChanged = True

    # add category key if not found
    for idx in pj[ETHOGRAM]:
        if "category" not in pj[ETHOGRAM][idx]:
            pj[ETHOGRAM][idx]["category"] = ""

    logging.debug("project_lowerthan4: {}".format(project_lowerthan4))

    if project_lowerthan4:

        copyfile(projectFileName,
                 projectFileName.replace(".boris", "_old_version.boris"))

        msg = (
            "O projeto foi atualizado para a versão atual do projeto ({project_format_version}).\n\n"
            "O projeto de arquivo antigo foi salvo como {project_file_name}"
        ).format(project_format_version=project_format_version,
                 project_file_name=projectFileName.replace(
                     ".boris", "_old_version.boris"))

    # if one file is present in player #1 -> set "media_info" key with value of media_file_info
    project_updated = False

    for obs in pj[OBSERVATIONS]:
        if pj[OBSERVATIONS][obs][TYPE] in [
                MEDIA
        ] and "media_info" not in pj[OBSERVATIONS][obs]:
            pj[OBSERVATIONS][obs]['media_info'] = {
                "length": {},
                "fps": {},
                "hasVideo": {},
                "hasAudio": {}
            }
            for player in [PLAYER1, PLAYER2]:
                # fix bug Anne Maijer 2017-07-17
                if pj[OBSERVATIONS][obs]["file"] == []:
                    pj[OBSERVATIONS][obs]["file"] = {"1": [], "2": []}

                for media_file_path in pj[OBSERVATIONS][obs]["file"][player]:
                    # FIX: ffmpeg path

                    ret, msg = utilities.check_ffmpeg_path()
                    if not ret:
                        return projectFileName, projectChanged, {
                            "error": "FFmpeg path not found"
                        }, ""
                    else:
                        ffmpeg_bin = msg

                    #nframe, videoTime, videoDuration, fps, hasVideo, hasAudio = utilities.accurate_media_analysis(ffmpeg_bin, media_file_path)
                    r = utilities.accurate_media_analysis2(
                        ffmpeg_bin, media_file_path)
                    if "error" in r:
                        return projectFileName, projectChanged, {
                            "error": r["error"]
                        }, ""

                    if r["duration"]:
                        pj[OBSERVATIONS][obs]["media_info"]["length"][
                            media_file_path] = r["duration"]
                        pj[OBSERVATIONS][obs]["media_info"]["fps"][
                            media_file_path] = r["fps"]
                        pj[OBSERVATIONS][obs]["media_info"]["hasVideo"][
                            media_file_path] = r["has_video"]
                        pj[OBSERVATIONS][obs]["media_info"]["hasAudio"][
                            media_file_path] = r["has_audio"]
                        project_updated, projectChanged = True, True
                    else:  # file path not found
                        if ("media_file_info" in pj[OBSERVATIONS][obs] and len(
                                pj[OBSERVATIONS][obs]["media_file_info"]) == 1
                                and len(pj[OBSERVATIONS][obs]["file"][PLAYER1])
                                == 1
                                and len(pj[OBSERVATIONS][obs]["file"][PLAYER2])
                                == 0):
                            media_md5_key = list(pj[OBSERVATIONS][obs]
                                                 ["media_file_info"].keys())[0]
                            # duration
                            pj[OBSERVATIONS][obs]["media_info"] = {
                                "length": {
                                    media_file_path:
                                    pj[OBSERVATIONS][obs]["media_file_info"]
                                    [media_md5_key]["video_length"] / 1000
                                }
                            }
                            project_updated, projectChanged = True, True

                            # FPS
                            if "nframe" in pj[OBSERVATIONS][obs][
                                    "media_file_info"][media_md5_key]:
                                pj[OBSERVATIONS][obs]['media_info']['fps'] = {
                                    media_file_path:
                                    pj[OBSERVATIONS][obs]['media_file_info']
                                    [media_md5_key]['nframe'] /
                                    (pj[OBSERVATIONS][obs]['media_file_info']
                                     [media_md5_key]['video_length'] / 1000)
                                }
                            else:
                                pj[OBSERVATIONS][obs]['media_info']['fps'] = {
                                    media_file_path: 0
                                }

    if project_updated:
        msg = "As informações dos arquivos de mídia foram atualizadas para o novo formato do projeto."

    return projectFileName, projectChanged, pj, msg
Esempio n. 14
0
def open_project_json(projectFileName):
    """
    open project json

    Args:
        projectFileName (str): path of project

    Returns:
        str: project path
        bool: True if project changed
        dict: BORIS project
        str: message
    """

    logging.debug("open project: {0}".format(projectFileName))

    projectChanged = False
    msg = ""

    if not os.path.isfile(projectFileName):
        return projectFileName, projectChanged, {"error": "File {} not found".format(projectFileName)}, msg

    try:
        s = open(projectFileName, "r").read()
    except PermissionError:
        return projectFileName, projectChanged, {"error": "File {}: Permission denied".format(projectFileName)}, msg
    except Exception:
        return projectFileName, projectChanged, {"error": "Error on file {}: {}".format(projectFileName, sys.exc_info()[1])}, msg

    try:
        pj = json.loads(s)
    except json.decoder.JSONDecodeError:
        return projectFileName, projectChanged, {"error": "This project file seems corrupted"}, msg
    except Exception:
        return projectFileName, projectChanged, {"error": "This project file seems corruptedError on file {}: {}".format(projectFileName, sys.exc_info()[1])}, msg

    # transform time to decimal
    pj = utilities.convert_time_to_decimal(pj)

    # add coding_map key to old project files
    if "coding_map" not in pj:
        pj["coding_map"] = {}
        projectChanged = True

    # add subject description
    if "project_format_version" in pj:
        for idx in [x for x in pj[SUBJECTS]]:
            if "description" not in pj[SUBJECTS][idx]:
                pj[SUBJECTS][idx]["description"] = ""
                projectChanged = True

    # check if project file version is newer than current BORIS project file version
    if "project_format_version" in pj and Decimal(pj["project_format_version"]) > Decimal(project_format_version):
        return (
            projectFileName,
            projectChanged,
            {
                "error": (
                    "This project file was created with a more recent version of BORIS.<br>"
                    "You must update BORIS to <b>v. >= {}</b> to open this project"
                ).format(pj["project_format_version"])
            },
            msg,
        )

    # check if old version  v. 0 *.obs
    if "project_format_version" not in pj:

        # convert VIDEO, AUDIO -> MEDIA
        pj["project_format_version"] = project_format_version
        projectChanged = True

        for obs in [x for x in pj[OBSERVATIONS]]:

            # remove 'replace audio' key
            if "replace audio" in pj[OBSERVATIONS][obs]:
                del pj[OBSERVATIONS][obs]["replace audio"]

            if pj[OBSERVATIONS][obs][TYPE] in ["VIDEO", "AUDIO"]:
                pj[OBSERVATIONS][obs][TYPE] = MEDIA

            # convert old media list in new one
            if len(pj[OBSERVATIONS][obs][FILE]):
                d1 = {PLAYER1: [pj[OBSERVATIONS][obs][FILE][0]]}

            if len(pj[OBSERVATIONS][obs][FILE]) == 2:
                d1[PLAYER2] = [pj[OBSERVATIONS][obs][FILE][1]]

            pj[OBSERVATIONS][obs][FILE] = d1

        # convert VIDEO, AUDIO -> MEDIA
        for idx in [x for x in pj[SUBJECTS]]:
            key, name = pj[SUBJECTS][idx]
            pj[SUBJECTS][idx] = {"key": key, "name": name, "description": ""}

        msg = (
            "The project file was converted to the new format (v. {}) in use with your version of BORIS.<br>"
            "Choose a new file name for saving it."
        ).format(project_format_version)
        projectFileName = ""

    # update modifiers to JSON format

    # check if project format version < 4 (modifiers were str)
    project_lowerthan4 = False
    if "project_format_version" in pj and utilities.versiontuple(pj["project_format_version"]) < utilities.versiontuple("4.0"):
        for idx in pj[ETHOGRAM]:
            if pj[ETHOGRAM][idx]["modifiers"]:
                if isinstance(pj[ETHOGRAM][idx]["modifiers"], str):
                    project_lowerthan4 = True
                    modif_set_list = pj[ETHOGRAM][idx]["modifiers"].split("|")
                    modif_set_dict = {}
                    for modif_set in modif_set_list:
                        modif_set_dict[str(len(modif_set_dict))] = {"name": "", "type": SINGLE_SELECTION, "values": modif_set.split(",")}
                    pj[ETHOGRAM][idx]["modifiers"] = dict(modif_set_dict)
            else:
                pj[ETHOGRAM][idx]["modifiers"] = {}

        if not project_lowerthan4:
            msg = "The project version was updated from {} to {}".format(pj["project_format_version"], project_format_version)
            pj["project_format_version"] = project_format_version
            projectChanged = True

    # add category key if not found
    for idx in pj[ETHOGRAM]:
        if "category" not in pj[ETHOGRAM][idx]:
            pj[ETHOGRAM][idx]["category"] = ""

    # if one file is present in player #1 -> set "media_info" key with value of media_file_info
    for obs in pj[OBSERVATIONS]:
        if pj[OBSERVATIONS][obs][TYPE] in [MEDIA] and MEDIA_INFO not in pj[OBSERVATIONS][obs]:
            pj[OBSERVATIONS][obs][MEDIA_INFO] = {LENGTH: {}, "fps": {}, "hasVideo": {}, "hasAudio": {}}
            for player in [PLAYER1, PLAYER2]:
                # fix bug Anne Maijer 2017-07-17
                if pj[OBSERVATIONS][obs][FILE] == []:
                    pj[OBSERVATIONS][obs][FILE] = {"1": [], "2": []}

                for media_file_path in pj[OBSERVATIONS][obs]["file"][player]:
                    # FIX: ffmpeg path
                    ret, msg = utilities.check_ffmpeg_path()
                    if not ret:
                        return projectFileName, projectChanged, {"error": "FFmpeg path not found"}, ""
                    else:
                        ffmpeg_bin = msg

                    r = utilities.accurate_media_analysis(ffmpeg_bin, media_file_path)

                    if "duration" in r and r["duration"]:
                        pj[OBSERVATIONS][obs][MEDIA_INFO][LENGTH][media_file_path] = float(r["duration"])
                        pj[OBSERVATIONS][obs][MEDIA_INFO][FPS][media_file_path] = float(r["fps"])
                        pj[OBSERVATIONS][obs][MEDIA_INFO]["hasVideo"][media_file_path] = r["has_video"]
                        pj[OBSERVATIONS][obs][MEDIA_INFO]["hasAudio"][media_file_path] = r["has_audio"]
                        project_updated, projectChanged = True, True
                    else:  # file path not found
                        if (
                            "media_file_info" in pj[OBSERVATIONS][obs] and
                            len(pj[OBSERVATIONS][obs]["media_file_info"]) == 1 and
                            len(pj[OBSERVATIONS][obs][FILE][PLAYER1]) == 1 and
                            len(pj[OBSERVATIONS][obs][FILE][PLAYER2]) == 0
                        ):
                            media_md5_key = list(pj[OBSERVATIONS][obs]["media_file_info"].keys())[0]
                            # duration
                            pj[OBSERVATIONS][obs][MEDIA_INFO] = {
                                LENGTH: {media_file_path: pj[OBSERVATIONS][obs]["media_file_info"][media_md5_key]["video_length"] / 1000}
                            }
                            projectChanged = True

                            # FPS
                            if "nframe" in pj[OBSERVATIONS][obs]["media_file_info"][media_md5_key]:
                                pj[OBSERVATIONS][obs][MEDIA_INFO][FPS] = {
                                    media_file_path: pj[OBSERVATIONS][obs]["media_file_info"][media_md5_key]["nframe"] /
                                    (pj[OBSERVATIONS][obs]["media_file_info"][media_md5_key]["video_length"] / 1000)
                                }
                            else:
                                pj[OBSERVATIONS][obs][MEDIA_INFO][FPS] = {media_file_path: 0}

    # update project to v.7 for time offset second player
    project_lowerthan7 = False
    for obs in pj[OBSERVATIONS]:
        if "time offset second player" in pj[OBSERVATIONS][obs]:
            if MEDIA_INFO not in pj[OBSERVATIONS][obs]:
                pj[OBSERVATIONS][obs][MEDIA_INFO] = {}
            if "offset" not in pj[OBSERVATIONS][obs][MEDIA_INFO]:
                pj[OBSERVATIONS][obs][MEDIA_INFO]["offset"] = {}
            for player in pj[OBSERVATIONS][obs][FILE]:
                pj[OBSERVATIONS][obs][MEDIA_INFO]["offset"][player] = 0.0
            if pj[OBSERVATIONS][obs]["time offset second player"]:
                pj[OBSERVATIONS][obs][MEDIA_INFO]["offset"]["2"] = float(pj[OBSERVATIONS][obs]["time offset second player"])

            del pj[OBSERVATIONS][obs]["time offset second player"]
            project_lowerthan7 = True

            msg = (
                "The project file was converted to the new format (v. {project_version}) in use with your version of BORIS.<br>"
                "Please note that this new version will NOT be compatible with previous BORIS versions (&lt; v. {project_version}).<br>"
            ).format(project_version=project_format_version)

            projectChanged = True


    if project_lowerthan7:

        msg = (
            "The project was updated to the current project version ({project_format_version})."
        ).format(project_format_version=project_format_version)

        try:
            copyfile(projectFileName, projectFileName.replace(".boris", ".v{}.boris".format(pj["project_format_version"])))
            msg += "\n\nThe old file project was saved as {}".format(projectFileName.replace(".boris", ".v{}.boris".format(pj["project_format_version"])))
        except Exception:
            pass

        pj["project_format_version"] = project_format_version

    return projectFileName, projectChanged, pj, msg