Skip to content

imarina_mapper

imarina_mapper

unparse_researcher_to_imarina_row

unparse_researcher_to_imarina_row(data: Researcher, empty_output_row: Excel) -> Any

Writes a Researcher's fields into row 0 of a single-row Excel, using the iMarina column names.

Parameters:

Name Type Description Default
data Researcher

The researcher whose fields are written out.

required
empty_output_row Excel

A one-row Excel (built from a copy of the output template) whose row 0 is filled in place.

required
Source code in source/src/imarina_load_researchers/core/imarina_mapper.py
def unparse_researcher_to_imarina_row(data: Researcher, empty_output_row: Excel) -> Any:
    """
    Writes a `Researcher`'s fields into row 0 of a single-row `Excel`, using
    the iMarina column names.

    Args:
        data (Researcher): The researcher whose fields are written out.
        empty_output_row (Excel): A one-row `Excel` (built from a copy of the
            output template) whose row 0 is filled in place.
    """
    empty_output_row.dataframe.at[0, ImarinaField.DNI.value] = data.dni
    empty_output_row.dataframe.at[0, ImarinaField.EMAIL.value] = data.email
    empty_output_row.dataframe.at[0, ImarinaField.ORCID.value] = data.orcid
    empty_output_row.dataframe.at[0, ImarinaField.NAME.value] = data.name
    empty_output_row.dataframe.at[0, ImarinaField.SURNAME.value] = data.surname
    empty_output_row.dataframe.at[0, ImarinaField.SECOND_SURNAME.value] = (
        data.second_surname
    )
    empty_output_row.dataframe.at[0, ImarinaField.INI_DATE.value] = unparse_date(
        data.ini_date
    )
    empty_output_row.dataframe.at[0, ImarinaField.END_DATE.value] = unparse_date(
        data.end_date
    )
    empty_output_row.dataframe.at[0, ImarinaField.SEX.value] = data.sex
    empty_output_row.dataframe.at[0, ImarinaField.PERSONAL_WEB.value] = (
        data.personal_web
    )
    empty_output_row.dataframe.at[0, ImarinaField.SIGNATURE.value] = data.signature
    empty_output_row.dataframe.at[0, ImarinaField.SIGNATURE_CUSTOM.value] = (
        data.signature_custom
    )
    empty_output_row.dataframe.at[0, ImarinaField.COUNTRY.value] = data.country
    empty_output_row.dataframe.at[0, ImarinaField.JOB_DESCRIPTION.value] = (
        data.job_description
    )
    empty_output_row.dataframe.at[0, ImarinaField.ADSCRIPTION_TYPE.value] = (
        data.adscription_type
    )
    empty_output_row.dataframe.at[0, ImarinaField.UNIT_GROUP.value] = data.unit_group
    empty_output_row.dataframe.at[0, ImarinaField.ENTITY_TYPE.value] = data.entity_type

    empty_output_row.dataframe.at[0, ImarinaField.ENTITY_COUNTRY.value] = (
        data.entity_country
    )
    empty_output_row.dataframe.at[0, ImarinaField.ENTITY_COMMUNITY.value] = (
        data.entity_community
    )
    empty_output_row.dataframe.at[0, ImarinaField.ENTITY_PROVINCE.value] = (
        data.entity_province
    )
    empty_output_row.dataframe.at[0, ImarinaField.ENTITY_CITY.value] = data.entity_city
    empty_output_row.dataframe.at[0, ImarinaField.ENTITY_POSTAL_CODE.value] = (
        data.entity_postal_code
    )
    empty_output_row.dataframe.at[0, ImarinaField.ENTITY_ADDRESS.value] = (
        data.entity_address
    )
    empty_output_row.dataframe.at[0, ImarinaField.ENTITY_WEB.value] = data.entity_web
    empty_output_row.dataframe.at[0, ImarinaField.SCOPUS_ID.value] = data.scopus_id
    empty_output_row.dataframe.at[0, ImarinaField.GOOGLE_SCHOLAR_ID.value] = (
        data.google_scholar_id
    )
    empty_output_row.dataframe.at[0, ImarinaField.CONTACT_PHONE.value] = (
        data.contact_phone
    )

parse_imarina_row_data

parse_imarina_row_data(row: Series) -> Researcher

Converts one row of the previous iMarina load into a Researcher.

Unlike a3_mapper.parse_a3_row_data, this reads an already-iMarina-format row, so no dictionary translation is applied - values are read, typed and normalized (dates sanitized, numeric IDs stringified, names normalized) but not translated.

Parameters:

Name Type Description Default
row Series

A row from the previous iMarina load's dataframe, indexed by ImarinaField.value column names.

required

Returns:

Name Type Description
Researcher Researcher

The researcher parsed from this row.

Source code in source/src/imarina_load_researchers/core/imarina_mapper.py
def parse_imarina_row_data(row: pd.Series) -> Researcher:
    """
    Converts one row of the previous iMarina load into a `Researcher`.

    Unlike `a3_mapper.parse_a3_row_data`, this reads an already-iMarina-format
    row, so no dictionary translation is applied - values are read, typed and
    normalized (dates sanitized, numeric IDs stringified, names normalized)
    but not translated.

    Args:
        row (pd.Series): A row from the previous iMarina load's dataframe,
            indexed by `ImarinaField.value` column names.

    Returns:
        Researcher: The researcher parsed from this row.
    """
    entity_type_val = get_str_val(row, ImarinaField.ENTITY_TYPE.value)
    entity_web_val = get_str_val(row, ImarinaField.ENTITY_WEB.value)
    entity_country_val = get_str_val(row, ImarinaField.ENTITY_COUNTRY.value)
    entity_community_val = get_str_val(row, ImarinaField.ENTITY_COMMUNITY.value)
    entity_province_val = get_str_val(row, ImarinaField.ENTITY_PROVINCE.value)
    entity_city_val = get_str_val(row, ImarinaField.ENTITY_CITY.value)
    entity_postal_code_val = get_str_val(row, ImarinaField.ENTITY_POSTAL_CODE.value)
    entity_address_val = get_str_val(row, ImarinaField.ENTITY_ADDRESS.value)
    contact_phone_val = get_str_val(row, ImarinaField.CONTACT_PHONE.value)

    scopus_id_val = get_val(row, ImarinaField.SCOPUS_ID.value)
    if scopus_id_val is not None:
        if isinstance(scopus_id_val, float) and scopus_id_val.is_integer():
            scopus_id_val = str(int(scopus_id_val))
        else:
            scopus_id_val = str(scopus_id_val).strip()
    else:
        scopus_id_val = ""

    google_scholar_val = (
        str(val).strip()
        if (val := get_val(row, ImarinaField.GOOGLE_SCHOLAR_ID.value)) is not None
        else ""
    )

    orcid_val = get_val(row, ImarinaField.ORCID.value)
    if orcid_val is None:
        orcid_val = ""

    job_description_val = get_val(row, ImarinaField.JOB_DESCRIPTION.value)
    if job_description_val:
        job_description_val = job_description_val.strip()

    email_val = get_val(row, ImarinaField.EMAIL.value)
    if email_val is not None:
        email_val = email_val.lower()

    data = Researcher(
        dni=get_val(row, ImarinaField.DNI.value),  # dni_val (value)
        email=email_val,
        orcid=orcid_val,  # orcid_val (value)
        name=normalize_name(get_val(row, ImarinaField.NAME.value) or ""),
        surname=normalize_name(get_val(row, ImarinaField.SURNAME.value) or ""),
        second_surname=normalize_name(
            get_val(row, ImarinaField.SECOND_SURNAME.value) or ""
        ),
        ini_date=sanitize_date(get_val(row, ImarinaField.INI_DATE.value)),
        end_date=sanitize_date(get_val(row, ImarinaField.END_DATE.value)),
        sex=get_val(row, ImarinaField.SEX.value),
        personal_web=get_val(row, ImarinaField.PERSONAL_WEB.value),
        signature=get_val(row, ImarinaField.SIGNATURE.value),
        signature_custom=get_val(row, ImarinaField.SIGNATURE_CUSTOM.value),
        country=str(get_val(row, ImarinaField.COUNTRY.value)).strip(),
        born_country=str(get_val(row, ImarinaField.COUNTRY.value)).strip(),
        job_description=job_description_val,
        adscription_type=get_val(row, ImarinaField.ADSCRIPTION_TYPE.value),
        unit_group=get_val(row, ImarinaField.UNIT_GROUP.value),
        entity_type=entity_type_val,  # entity_type_val (value)
        entity_web=entity_web_val,  # entity_web_val (value)
        entity_country=entity_country_val,
        entity_community=entity_community_val,
        entity_province=entity_province_val,
        entity_city=entity_city_val,
        entity_postal_code=entity_postal_code_val,
        entity_address=entity_address_val,
        scopus_id=str(scopus_id_val),
        google_scholar_id=google_scholar_val,
        contact_phone=contact_phone_val,
    )

    return data

append_researchers_to_output_data

append_researchers_to_output_data(researchers: list[Any], output_data: Any) -> None

Appends one output row per researcher onto the output Excel, in place.

Builds a single empty (all-None) template row from output_data's own columns, then for each researcher fills a fresh copy of that row via unparse_researcher_to_imarina_row and concatenates it onto output_data.

Parameters:

Name Type Description Default
researchers list[Any]

The Researchers to append, in order.

required
output_data Any

The output Excel (already carrying the iMarina column headers) that rows are appended to, in place.

required
Source code in source/src/imarina_load_researchers/core/imarina_mapper.py
def append_researchers_to_output_data(researchers: list[Any], output_data: Any) -> None:
    """
    Appends one output row per researcher onto the output `Excel`, in place.

    Builds a single empty (all-`None`) template row from `output_data`'s own
    columns, then for each researcher fills a fresh copy of that row via
    `unparse_researcher_to_imarina_row` and concatenates it onto `output_data`.

    Args:
        researchers (list[Any]): The `Researcher`s to append, in order.
        output_data (Any): The output `Excel` (already carrying the iMarina
            column headers) that rows are appended to, in place.
    """
    empty_row_output_data = output_data.__copy__()
    empty_row_output_data.empty()
    empty_row_output_data.dataframe.loc[0] = [None] * len(
        empty_row_output_data.dataframe.columns
    )
    for researcher in researchers:
        new_row = empty_row_output_data.__copy__()
        unparse_researcher_to_imarina_row(researcher, new_row)
        output_data.concat(new_row)