Skip to content
Snippets Groups Projects
Commit 4cd64b2f authored by Duchateau Fabien's avatar Duchateau Fabien
Browse files

[MD] deleted all files + updated README with links to gitlab.com

parent 3911efd3
No related branches found
No related tags found
No related merge requests found
0,P14_RSECOCC,P14_NPER_RP_LOCHLMV,C14_PMEN_MENCOUPSENF,P14_POP0205,P14_RPAPPART_ACH19,C14_ACT1564_CS5,C14_ACTOCC1564_CS3,P14_RPAPPART_ACH70,DEC_D414,C14_PMEN_CS5,P14_ACTOCC15P_TP,P14_NBPI_RPMAISON,C14_PMEN_CS3,P14_RP_ACH19,P14_SAL15P_APPR,P14_RP_CCCOLL,P14_ANEM_RP_PROP,P14_ANEM_RP,P14_POP1524_PSEUL,P14_ACTOCC15P_ILT2,NB_A504,P14_PMEN_ANEM0509,P14_MAISON,P14_RP_VOIT1P,C14_PMEN_MENCOUPAENF,AREA,P14_POP1824,P14_ACTOCC15P_ILT2P,P14_NSCOL15P_SUP,DENSITY,P14_ACT1524,C14_PMEN_CS2,P14_RPAPPART,P14_RPMAISON_ACHTOT,P14_RP_PROP,P14_NBPI_RPAPPART,P14_RPMAISON_ACH90,P14_RPMAISON,P14_POP,P14_RP_CCIND,C14_MEN_CS8,C14_NE24F3,P14_SCOL1824,DEC_D614,P14_RP_80100M2,C14_POP15P_CS3,P14_RPMAISON_ACH45,P14_ANEM_RP_LOCHLMV,P14_PMEN_ANEM10P,C14_ACTOCC15P_DROU,C14_PMEN_MENFAM,P14_SCOL1114,P14_RP_ACH90,C14_PMEN_CS6,DEC_D214,DEC_D914,C14_MENFSEUL,C14_NE24F2,P14_NPER_RP_PROP,P14_RP_GARL,C14_ACT1564_CS3,C14_ACTOCC15P_MAR,P14_RP_5PP,P14_RP_LOC,P14_SCOL1517,C14_PMEN,P14_ACTOCC15P_ILT1
1,P14_RSECOCC,P14_NPER_RP_LOCHLMV,P14_NSCOL15P_CAPBEP,P14_PMEN_ANEM0002,C14_POP15P_CS8,C14_NE24F1,C14_ACTOCC1564_CS3,P14_POP4559,P14_RP_ACH11,C14_PMEN_CS5,DEC_D414,P14_RP_3040M2,C14_PMEN_CS3,P14_POP1524_PSEUL,P14_RPAPPART_ACH90,P14_RP_CCCOLL,P14_ANEM_RP_PROP,P14_RP_ACH45,P14_ACTOCC15P_ILT2,NB_A504,P14_RP_3P,P14_PMEN_ANEM0509,P14_NPER_RP_LOC,P14_POP0610,AREA,C14_PMEN_MENCOUPAENF,P14_POP15P,P14_NBPI_RP_ANEM0509,C14_MEN_CS6,DENSITY,P14_AINACT1564,P14_RP_PROP,P14_RPAPPART,P14_RPMAISON_ACHTOT,P14_POPMEN5579,P14_POP2064,C14_MENSFAM,P14_POP,C14_FAMMONO,P14_RP_4060M2,P14_SCOL1824,C14_POP15P_CS3,P14_POP1524,P14_ANEM_RP_LOCHLMV,P14_RP_LOCHLMV,C14_MENCOUPAENF,C14_PMEN_MENFAM,C14_ACTOCC1564,P14_POP4054,P14_RP_ACH90,P14_ANEM_RP_LOC,C14_PMEN_CS6,C14_ACTOCC15P_PAS,P14_NPER_RP_PROP,C14_ACT1564_CS3,C14_PMEN_MENSFAM,P14_POP0019,C14_POP15P_CS4,P14_APPART,DEC_D214,P14_RP_ACH05,DEC_D114,P14_POP_IMM,,,,
2,P14_NPER_RP_LOCHLMV,P14_RP_6080M2,P14_PMEN_ANEM0002,C14_POP15P_CS8,P14_POP15P_MARIEE,P14_RPAPPART_ACH19,P14_PMEN,C14_ACTOCC1564_CS3,DEC_Q114,DEC_D314,P14_RPAPPART_ACH70,DEC_D414,C14_PMEN_CS7,C14_PMEN_CS3,P14_POP1524_PSEUL,P14_ANEM_RP,P14_RP_3040M2,P14_ANEM_RP_PROP,P14_POP15P,P14_ACTOCC15P_ILT2,NB_A504,P14_RP_ACH45,P14_PMEN_ANEM0509,P14_POP0610,P14_RP_2P,AREA,P14_POP5579,DEC_Q314,C14_PMEN_CS4,P14_NSCOL15P,P14_ACTOCC15P_ILT2P,P14_NSCOL15P_SUP,DENSITY,P14_RP_M30M2,P14_RPAPPART_ACH45,P14_RP_1P,P14_POP0014,P14_POPMEN1524,P14_POPMEN5579,P14_RP_VOIT2P,P14_RP_PROP,C14_PMEN_CS2,P14_RPMAISON_ACH90,P14_NBPI_RPAPPART,C14_MENSFAM,P14_POP,P14_SAL15P,C14_ACTOCC1564_CS6,P14_SCOL1824,DEC_D614,P14_RP_80100M2,P14_MEN_ANEM0204,P14_ANEM_RP_LOCHLMV,P14_RP_LOCHLMV,C14_PMEN_MENFAM,P14_ACTOCC1524,DEC_D814,DEC_D914,P14_RP_4P,C14_NE24F2,P14_NPER_RP_PROP,C14_PMEN_MENSFAM,P14_APPART,DEC_D214,DEC_D114,,
3,P14_NPER_RP_LOCHLMV,C14_MENFAMMONO,P14_RP_VOIT1,P14_NSCOL15P_CAPBEP,C14_PMEN_MENCOUPSENF,P14_ACTOCC15P_ILT3,P14_RPAPPART_ACH19,P14_PMEN,P14_NSAL15P_INDEP,P14_RPAPPART_ACH70,DEC_D414,P14_POP1117,P14_RP_CCCOLL,C14_PMEN_CS3,P14_RP_ACH19,P14_RP_3040M2,P14_NBPI_RPMAISON,C14_ACT1564_CS6,P14_ANEM_RP_PROP,P14_ANEM_RP,P14_ACTOCC15P_ILT2,P14_MAISON,P14_PMEN_ANEM0509,P14_POP0610,P14_RP_ACH70,AREA,P14_POP1824,C14_MEN_CS3,P14_MEN_ANEM0002,C14_ACTOCC15P,P14_ACTOCC15P_ILT2P,P14_NSCOL15P_SUP,P14_PMEN_ANEM0204,DENSITY,P14_RP_M30M2,P14_POPMEN1524,P14_RP_1P,P14_ACT1524,C14_PMEN_MENFAMMONO,P14_POP0014,P14_RPMAISON_ACHTOT,P14_RPAPPART,P14_RPMAISON_ACH90,P14_POP,P14_RP_4060M2,P14_POP1524,P14_RPAPPART_ACHTOT,C14_ACTOCC1564_CS2,P14_POP_ETR,P14_ANEM_RP_LOCHLMV,P14_ACTOCC2554,P14_LOGVAC,C14_PMEN_MENFAM,P14_PMEN_ANEM10P,P14_RP_ACH90,C14_PMEN_CS6,P14_NPER_RP_PROP,C14_ACTOCC15P_TCOM,P14_NSCOL15P_DIPLMIN,C14_ACT1564_CS2,P14_NBPI_RP_ANEM0204,C14_ACTOCC15P_MAR,P14_APPART,P14_NSCOL15P_BAC,C14_PMEN,P14_ACTOCC15P_ILT1,P14_POP_IMM
4,P14_NPER_RP_LOCHLMV,P14_RP_CINDELEC,P14_ACTOCC15P_ILT3,P14_RPAPPART_ACH19,C14_ACTOCC1564_CS3,P14_RPAPPART_ACH70,DEC_D414,P14_SCOL0205,P14_RP_CCCOLL,C14_PMEN_CS3,P14_POP1524_PSEUL,P14_RP_ACH19,P14_RPAPPART_ACH90,P14_ANEM_RP_PROP,P14_RP_ACH45,P14_ACTOCC15P_ILT2,P14_RP_ACH70,P14_NPER_RP_LOC,AREA,P14_POP6579,C14_PMEN_CS8,DEC_Q314,DENSITY,P14_RP_M30M2,P14_APPART,P14_RP_1P,P14_RPMAISON_ACH90,P14_RPMAISON,P14_POP,P14_POP15P_NONMARIEE,C14_MEN_CS8,P14_POP_ETR,P14_RPAPPART_ACH11,DEC_D614,C14_POP15P_CS3,P14_SCOL1824,P14_ANEM_RP_LOCHLMV,P14_RP_LOCHLMV,P14_LOGVAC,P14_RP_4060M2,P14_NBPI_RP_ANEM0002,DEC_D114,P14_ANEM_RP_GRAT,P14_ANEM_RP_LOC,P14_RP_ACH90,DEC_D814,DEC_D214,P14_RPAPPART_ACH05,C14_ACTOCC15P_TCOM,C14_POP15P_CS7,C14_ACT1564_CS3,P14_RP_GARL,C14_PMEN_MENSFAM,C14_ACTOCC15P_MAR,P14_RP_LOC,P14_RP_ACH11,P14_ACTOCC15P_ILT1,,,,,,,,,,
5,P14_RSECOCC,P14_NPER_RP_LOCHLMV,C14_MENHSEUL,P14_RP_CINDELEC,P14_ACTOCC15P_ILT3,P14_RPAPPART_ACH19,DEC_Q114,C14_ACTOCC1564_CS3,DEC_D314,P14_RPAPPART_ACH70,DEC_D414,C14_PMEN_CS5,P14_RP_CCCOLL,C14_PMEN_CS3,P14_RP_ACH19,P14_CHOM1524,P14_ANEM_RP_PROP,P14_RP_ACH45,P14_RP_2P,P14_NPER_RP_LOC,P14_NSAL15P,AREA,P14_POP1824,DEC_D714,C14_MEN_CS3,DEC_Q314,P14_MEN_ANEM0002,P14_ACTOCC15P_ILT2P,DEC_MED14,C14_ACTOCC15P_VOIT,P14_RP,P14_ACTOCC15P_ILT1,DENSITY,P14_RP_M30M2,P14_RPAPPART_ACH45,P14_RP_1P,P14_ACT1524,P14_POP,C14_MEN_CS8,P14_POP_ETR,P14_RP_4060M2,DEC_D614,C14_POP15P_CS3,P14_ANEM_RP_GRAT,P14_ANEM_RP_LOCHLMV,P14_NBPI_RP_ANEM0002,P14_LOGVAC,P14_ANEM_RP_LOC,C14_PMEN_CS6,DEC_D814,DEC_D914,C14_MENFSEUL,P14_RPAPPART_ACH05,P14_RP_GARL,C14_ACT1564_CS3,C14_PMEN_MENSFAM,P14_SCOL30P,P14_POP1529,DEC_D114,P14_POP_IMM,,,,,,,
0,P14_POP0002,P14_RP_6080M2,P14_RPAPPART_ACH70,P14_ANEM_RP,P14_POP0610,AREA,P14_POP1824,P14_NSCOL15P_SUP,DENSITY,P14_RPMAISON,P14_POP,C14_NE24F3,P14_SCOL1824,DEC_D614,P14_ANEM_RP_LOCHLMV,P14_SCOL1114,DEC_D814,DEC_D914,P14_NPER_RP_PROP,C14_ACTOCC15P_MAR,P14_APPART,P14_POP1529,P14_NPER_RP_LOCHLMV,P14_RPAPPART_ACH19,DEC_D414,P14_RP_CCCOLL,C14_PMEN_CS3,P14_RP_ACH19,P14_INACT1564,P14_ANEM_RP_PROP,P14_CHOM1564,P14_ACTOCC15P_ILT2,P14_MAISON,P14_PMEN_ANEM0509,P14_RP_VOIT1P,P14_ACTOCC15P_ILT2P,P14_RP_PROP,P14_POP1524,P14_PMEN_ANEM10P,C14_ACTOCC15P_DROU,C14_PMEN_MENFAM,P14_RP_ACH90,C14_PMEN_CS6,C14_MENFSEUL,C14_NE24F2,C14_ACT1564_CS3,DEC_D214,P14_ACTOCC15P_ILT1,P14_POP_IMM,P14_RSECOCC,C14_ACT1564_CS5,C14_PMEN_CS5,P14_NBPI_RPMAISON,P14_POP1524_PSEUL,NB_A504,C14_MEN_CS6,P14_ACT1524,C14_PMEN_CS2,P14_RPAPPART,P14_RPMAISON_ACHTOT,P14_RPMAISON_ACH90,P14_NBPI_RPAPPART,P14_RP_GARL,P14_RP_LOC,C14_PMEN,C14_PMEN_MENCOUPSENF,P14_POP0205,C14_ACTOCC1564_CS3,P14_ACTOCC15P_TP,P14_SAL15P_APPR,C14_PMEN_MENCOUPAENF,DEC_D714,P14_RPAPPART_ACH45,P14_CHOM2554,P14_RP_CCIND,C14_MEN_CS8,P14_RP_80100M2,C14_POP15P_CS3,P14_RPMAISON_ACH45,C14_ACTOCC1564_CS2,P14_RP_5PP,P14_SCOL1517
1,P14_POPMEN2554,P14_PMEN_ANEM0002,P14_RP_3040M2,P14_ANEM_RP,P14_RP_3P,P14_POP0610,AREA,P14_MEN_ANEM0002,P14_NSCOL15P_SUP,DENSITY,P14_POP0014,P14_POPMEN5579,P14_POP,P14_SCOL1824,P14_ANEM_RP_LOCHLMV,P14_RP_LOCHLMV,C14_ACTOCC1564,P14_POP4054,DEC_D914,P14_NPER_RP_PROP,P14_APPART,P14_RP_ACH05,DEC_D114,P14_NPER_RP_LOCHLMV,C14_POP15P_CS6,DEC_D414,P14_RP_CCCOLL,C14_PMEN_CS3,P14_RP_ACH19,P14_ANEM_RP_PROP,P14_ACTOCC15P_ILT2,P14_RP_2P,P14_PMEN_ANEM0509,P14_RP_VOIT1P,P14_NBPI_RP_ANEM0509,P14_AINACT1564,P14_RP_PROP,C14_FAMMONO,P14_POP1524,P14_RPAPPART_ACHTOT,C14_PMEN_MENFAM,P14_RP_ACH90,P14_NBPI_RP,C14_PMEN_CS6,C14_ACT1564_CS3,P14_RP_ACH11,DEC_D214,P14_POP_IMM,P14_RSECOCC,C14_NE24F1,P14_POP4559,C14_PMEN_CS5,P14_POP1524_PSEUL,P14_RP_ACH45,NB_A504,P14_NPER_RP_LOC,DEC_MED14,C14_MEN_CS6,P14_RPAPPART,P14_RPMAISON_ACHTOT,P14_RPMAISON_ACH90,P14_POP2064,C14_COUPAENF,C14_MENCOUPAENF,P14_ANEM_RP_LOC,C14_ACTOCC15P_PAS,P14_POP0019,C14_POP15P_CS4,P14_NSCOL15P_CAPBEP,C14_POP15P_CS8,C14_ACTOCC1564_CS3,P14_RPAPPART_ACH90,P14_POP15P,C14_PMEN_MENCOUPAENF,DEC_Q314,P14_RP_1P,C14_MENSFAM,P14_RP_4060M2,C14_POP15P_CS3,C14_PMEN_MENSFAM,,
2,P14_RP_6080M2,P14_PMEN_ANEM0002,P14_PMEN,DEC_Q114,P14_RPAPPART_ACH70,P14_RP_3040M2,P14_ANEM_RP,P14_POP0610,AREA,P14_NSCOL15P_SUP,DENSITY,P14_POP0014,P14_POPMEN1524,P14_POPMEN5579,P14_RP_VOIT2P,P14_POP,P14_SCOL1824,DEC_D614,P14_MEN_ANEM0204,P14_ANEM_RP_LOCHLMV,P14_RP_LOCHLMV,P14_ACTOCC1524,DEC_D814,DEC_D914,P14_RP_4P,P14_NPER_RP_PROP,C14_ACTOCC15P_MAR,P14_APPART,DEC_D114,P14_NPER_RP_LOCHLMV,P14_POP15P_MARIEE,P14_RPAPPART_ACH19,P14_POP2529,DEC_D414,C14_PMEN_CS7,C14_PMEN_CS3,P14_ANEM_RP_PROP,P14_ACTOCC15P_ILT2,P14_RP_2P,P14_PMEN_ANEM0509,P14_POP2554,P14_ACTOCC15P_ILT2P,P14_RP_M30M2,P14_RP_PROP,C14_ACTOCC1564_CS6,P14_NPER_RP_GRAT,C14_PMEN_MENFAM,P14_NBPI_RP,C14_POP15P_CS2,C14_NE24F2,DEC_D214,P14_NSCOL15P_BAC,P14_POP1524_PSEUL,P14_RP_ACH45,NB_A504,P14_POP5579,C14_PMEN_CS4,DEC_MED14,C14_PMEN_CS2,P14_RPMAISON_ACH90,P14_NBPI_RPAPPART,P14_ANEM_RP_LOC,P14_POP30P,C14_ACTOCC15P_TCOM,P14_RP_ACHTOT,C14_POP15P_CS8,C14_ACTOCC1564_CS3,DEC_D314,P14_RPAPPART_ACH90,P14_RPMAISON_ACH11,P14_POP15P,DEC_Q314,P14_NSCOL15P,P14_RPAPPART_ACH45,P14_RP_1P,C14_MENSFAM,P14_SAL15P,P14_RPAPPART_ACH11,P14_RP_80100M2,C14_PMEN_MENSFAM,,
3,P14_ACTOCC15P_ILT3,P14_PMEN,P14_NSAL15P_INDEP,P14_RPAPPART_ACH70,P14_RP_3040M2,C14_ACT1564_CS6,P14_NBPI_RP_ANEM10P,P14_ANEM_RP,P14_POP0610,AREA,P14_POP1824,P14_MEN_ANEM0002,P14_NSCOL15P_SUP,DENSITY,P14_POP0014,P14_POPMEN1524,P14_RPMAISON,P14_POP,P14_ANEM_RP_LOCHLMV,P14_LOGVAC,P14_NPER_RP_PROP,P14_NSCOL15P_DIPLMIN,C14_ACTOCC15P_MAR,P14_APPART,P14_ACTOCC2554,P14_NPER_RP_LOCHLMV,P14_RP_VOIT1,P14_POP15P_MARIEE,P14_RPAPPART_ACH19,DEC_D414,P14_POP1117,P14_RP_CCCOLL,C14_PMEN_CS3,P14_RP_ACH19,P14_ANEM_RP_PROP,P14_ACTOCC15P_ILT2,P14_MAISON,C14_MEN_CS2,P14_PMEN_ANEM0509,P14_RP_ACH70,P14_RP_2P,P14_ACTOCC15P_ILT2P,P14_RP_M30M2,C14_PMEN_MENFAMMONO,P14_POP1524,P14_RPAPPART_ACHTOT,P14_PMEN_ANEM10P,C14_PMEN_MENFAM,P14_RP_ACH90,C14_PMEN_CS6,C14_ACT1564_CS3,P14_NSCOL15P_BAC,P14_ACTOCC15P_ILT1,P14_POP_IMM,P14_RSECOCC,C14_MENFAMMONO,P14_ACTOCC1564,P14_NBPI_RPMAISON,C14_ACTOCC15P,DEC_MED14,P14_ACT1524,P14_RPMAISON_ACHTOT,P14_RPAPPART,P14_RPMAISON_ACH90,P14_POP_ETR,P14_NBPI_RP_ANEM0002,P14_ANEM_RP_LOC,C14_ACTOCC15P_PAS,P14_RPAPPART_ACH05,C14_ACTOCC15P_TCOM,C14_PMEN,P14_NSCOL15P_CAPBEP,C14_PMEN_MENCOUPSENF,DEC_D714,C14_MEN_CS3,P14_PMEN_ANEM0204,P14_RP_1P,P14_RP_CCIND,P14_RP_4060M2,C14_ACTOCC1564_CS2,C14_ACT1564_CS2,P14_NBPI_RP_ANEM0204
4,P14_NPER_RP_LOCHLMV,P14_RSECOCC,P14_RP_CINDELEC,P14_RP_6080M2,C14_NE24F1,P14_ACTOCC15P_ILT3,P14_RPAPPART_ACH19,DEC_Q114,C14_ACTOCC1564_CS3,P14_RPAPPART_ACH70,DEC_D414,P14_SCOL0205,P14_RP_CCCOLL,C14_PMEN_CS3,P14_POP1524_PSEUL,P14_RP_ACH19,P14_RPAPPART_ACH90,P14_ANEM_RP_PROP,P14_PHORMEN,P14_RP_ACH45,P14_ACTOCC15P_ILT2,P14_RP_ACH70,P14_NPER_RP_LOC,AREA,P14_POP6579,DEC_D714,C14_PMEN_CS8,P14_RP_120M2P,DEC_Q314,P14_ACTOCC15P_ILT2P,P14_NSCOL15P_SUP,DENSITY,P14_RP_M30M2,P14_RPAPPART_ACH45,P14_RP_1P,P14_APPART,P14_POPMEN5579,P14_ACTOCC5564,P14_RPMAISON_ACH90,P14_NBPI_RPAPPART,P14_RPMAISON,P14_POP,P14_POP15P_NONMARIEE,P14_RPAPPART_ACHTOT,C14_MEN_CS8,P14_POP_ETR,P14_RPAPPART_ACH11,DEC_D614,C14_POP15P_CS3,P14_SCOL1824,P14_ANEM_RP_LOCHLMV,P14_RP_LOCHLMV,P14_LOGVAC,P14_RP_4060M2,P14_NBPI_RP_ANEM0002,DEC_D114,P14_ANEM_RP_GRAT,P14_ANEM_RP_LOC,P14_RP_ACH90,DEC_D814,DEC_D214,P14_RPAPPART_ACH05,C14_ACTOCC15P_TCOM,C14_POP15P_CS7,C14_ACT1564_CS3,P14_RP_GARL,C14_PMEN_MENSFAM,C14_ACTOCC15P_MAR,P14_RP_LOC,P14_RP_ACH11,P14_ACTOCC15P_ILT1,,,,,,,,,,,
5,C14_POP15P,P14_MEN_ANEM10P,P14_ACTOCC15P_ILT3,DEC_Q114,P14_RPAPPART_ACH70,P14_NBPI_RP_ANEM10P,P14_NSAL15P,AREA,P14_POP1824,P14_MEN_ANEM0002,DENSITY,P14_POPMEN1524,P14_POP,DEC_D614,P14_ANEM_RP_LOCHLMV,P14_LOGVAC,P14_POP4054,DEC_D814,DEC_D914,P14_POP1529,P14_RP_ACH05,DEC_D114,P14_NPER_RP_LOCHLMV,P14_RP_VOIT1,C14_MENHSEUL,P14_RPAPPART_ACH19,DEC_D414,P14_RP_CCCOLL,C14_PMEN_CS3,P14_RP_ACH19,P14_CHOM1524,P14_ANEM_RP_PROP,P14_RP_2P,P14_RP_ACH70,P14_ACTOCC15P_ILT2P,P14_RP,P14_RP_M30M2,P14_POP15P_NONMARIEE,P14_POPMEN15P,C14_PMEN_CS6,C14_MENFSEUL,C14_ACT1564_CS3,DEC_D214,P14_ACTOCC15P_ILT1,P14_POP_IMM,P14_RSECOCC,P14_RP_CINDELEC,C14_PMEN_CS5,P14_POP1524_PSEUL,P14_RP_ACH45,P14_NPER_RP_LOC,DEC_MED14,C14_MEN_CS6,P14_ACT1524,P14_NBPI_RPAPPART,P14_POP_ETR,P14_ANEM_RP_GRAT,P14_NBPI_RP_ANEM0002,P14_ANEM_RP_LOC,P14_RPAPPART_ACH05,C14_ACTOCC15P_TCOM,P14_RP_GARL,P14_SCOL30P,C14_ACTOCC1564_CS3,DEC_D314,DEC_D714,C14_MEN_CS3,P14_NSCOL15P,DEC_Q314,C14_ACTOCC15P_VOIT,P14_RPAPPART_ACH45,P14_RP_1P,C14_MENSFAM,C14_MEN_CS8,P14_RP_4060M2,C14_POP15P_CS3,C14_PMEN_MENSFAM,,,,,
0,P14_POP0002,P14_POPMEN2554,P14_RP_6080M2,P14_RPAPPART_ACH70,P14_RP_3040M2,P14_ANEM_RP,P14_POP0610,AREA,P14_POP1824,P14_NSCOL15P_SUP,P14_LOG,DENSITY,C14_MENPSEUL,P14_POP2539,P14_POPMEN5579,P14_RPMAISON,P14_POP,C14_NE24F3,P14_SCOL1824,DEC_D614,P14_ANEM_RP_LOCHLMV,P14_SCOL1114,DEC_D814,DEC_D914,P14_NPER_RP_PROP,C14_ACTOCC15P_MAR,P14_APPART,P14_POP1529,P14_RP_ACH05,DEC_D114,P14_NPER_RP_LOCHLMV,P14_RPAPPART_ACH19,DEC_D414,P14_ACTOCC15P_ILT5,P14_RP_CCCOLL,C14_PMEN_CS3,P14_RP_ACH19,P14_INACT1564,P14_ANEM_RP_PROP,P14_CHOM1564,P14_ACTOCC15P_ILT2,P14_MAISON,P14_PMEN_ANEM0509,P14_RP_2P,P14_RP_VOIT1P,P14_POP2554,P14_ACTOCC15P_ILT2P,P14_RP_M30M2,P14_RP_PROP,P14_NPER_RP_GRAT,P14_POP1524,P14_RPAPPART_ACHTOT,P14_PMEN_ANEM10P,C14_ACTOCC15P_DROU,C14_PMEN_MENFAM,P14_RP_ACH90,P14_NBPI_RP,C14_PMEN_CS6,C14_MENFSEUL,C14_NE24F2,C14_ACT1564_CS3,DEC_D214,P14_ACTOCC15P_ILT1,P14_POP_IMM,P14_RSECOCC,C14_ACT1564_CS5,C14_PMEN_CS5,P14_NBPI_RPMAISON,P14_POP1524_PSEUL,P14_RP_ACH45,NB_A504,C14_PMEN_CS4,C14_ACTOCC15P,C14_MEN_CS6,P14_ACT1524,C14_PMEN_CS2,P14_RPAPPART,P14_RPMAISON_ACHTOT,P14_RPMAISON_ACH90,P14_NBPI_RPAPPART,C14_POP15P_CS5,P14_ANEM_RP_GRAT,C14_ACTOCC15P_PAS,P14_POP30P,P14_RP_GARL,P14_POP0019,P14_ACT2554,P14_RP_LOC,C14_PMEN,C14_ACT1564_CS4,C14_PMEN_MENCOUPSENF,P14_POP0205,C14_ACTOCC1564_CS3,DEC_D314,P14_ACTOCC15P_TP,P14_RPAPPART_ACH90,P14_SAL15P_APPR,P14_POP15P,C14_PMEN_MENCOUPAENF,DEC_D714,C14_MEN_CS3,P14_RPAPPART_ACH45,P14_RP_1P,P14_CHOM2554,P14_RP_CCIND,C14_MEN_CS8,P14_RP_80100M2,C14_POP15P_CS3,P14_RPMAISON_ACH45,C14_ACTOCC1564_CS2,C14_ACT1564_CS2,P14_RP_5PP,P14_SCOL1517,,,,,
1,P14_POPMEN2554,P14_PMEN_ANEM0002,P14_PMEN,DEC_Q114,P14_RPAPPART_ACH70,P14_SCOL0205,P14_RP_3040M2,P14_ANEM_RP,P14_RP_3P,P14_POP0610,AREA,P14_MEN_ANEM0002,P14_NSCOL15P_SUP,P14_LOG,DENSITY,P14_POP0014,C14_MENPSEUL,P14_POPMEN1524,P14_POP2539,P14_POPMEN5579,P14_POP,C14_MENCOUPSENF,P14_SCOL1824,P14_MEN_ANEM0204,P14_ANEM_RP_LOCHLMV,P14_RP_LOCHLMV,P14_LOGVAC,C14_ACTOCC1564,P14_POP4054,DEC_D914,P14_NPER_RP_PROP,P14_POP0305,P14_APPART,P14_RP_ACH05,P14_ACTOCC2554,DEC_D114,P14_NPER_RP_LOCHLMV,C14_POP15P_CS6,P14_RPAPPART_ACH19,DEC_D414,P14_RP_CCCOLL,C14_PMEN_CS3,P14_RP_ACH19,P14_ANEM_RP_PROP,P14_SCOL2529,P14_ACTOCC15P_ILT2,P14_RP_2P,P14_PMEN_ANEM0509,P14_RP_VOIT1P,P14_SAL15P_CDI,P14_NBPI_RP_ANEM0509,P14_ACTOCC15P_ILT2P,P14_AINACT1564,C14_PMEN_MENFAMMONO,P14_RP_PROP,C14_FAMMONO,P14_POP1524,P14_RPAPPART_ACHTOT,P14_POP_FR,C14_PMEN_MENFAM,P14_RP_ACH90,P14_NBPI_RP,C14_PMEN_CS6,C14_POP15P_CS7,C14_ACT1564_CS3,P14_F1529,P14_RP_ACH11,DEC_D214,P14_ACTOCC15P_ILT1,P14_POP_IMM,P14_RSECOCC,C14_NE24F1,P14_POP4559,C14_PMEN_CS5,P14_POP1524_PSEUL,P14_RP_ACH45,NB_A504,P14_NPER_RP_LOC,C14_ACTOCC15P,DEC_MED14,C14_MEN_CS6,P14_RPAPPART,P14_RPMAISON_ACHTOT,P14_NBPI_RPAPPART,P14_RPMAISON_ACH90,P14_POP2064,C14_COUPAENF,C14_MENCOUPAENF,P14_ANEM_RP_LOC,C14_ACTOCC15P_PAS,P14_POP30P,P14_ACTOCC15P,P14_POP0019,C14_POP15P_CS4,P14_RP_LOC,P14_NSCOL15P_CAPBEP,C14_POP15P_CS8,C14_ACTOCC1564_CS3,DEC_D314,P14_RPAPPART_ACH90,P14_POP15P,C14_PMEN_MENCOUPAENF,C14_MEN_CS3,DEC_Q314,P14_NSCOL15P,P14_RP_GRAT,P14_RPAPPART_ACH45,P14_RP_1P,C14_MENSFAM,P14_RP_4060M2,C14_POP15P_CS3,C14_PMEN_MENSFAM,P14_NBPI_RP_ANEM0204,DEC_TP6014,,,,
2,P14_POP0002,P14_RP_6080M2,P14_PMEN_ANEM0002,P14_PMEN,DEC_Q114,P14_RPAPPART_ACH70,P14_RP_3040M2,P14_ANEM_RP,P14_POP0610,AREA,P14_POP1824,P14_NSCOL15P_SUP,DENSITY,P14_POP0014,C14_MENPSEUL,P14_POPMEN1524,P14_POPMEN5579,P14_RP_VOIT2P,P14_RPMAISON,P14_POP,P14_SCOL1824,DEC_D614,P14_MEN_ANEM0204,P14_ANEM_RP_LOCHLMV,P14_RP_LOCHLMV,C14_MEN_CS7,C14_ACTOCC1564,P14_ACTOCC1524,DEC_D814,DEC_D914,P14_RP_4P,P14_NPER_RP_PROP,P14_F3044,C14_ACTOCC15P_MAR,P14_APPART,DEC_D114,P14_NPER_RP_LOCHLMV,P14_RP_VOIT1,C14_MENHSEUL,P14_POP15P_MARIEE,P14_RPAPPART_ACH19,P14_POP2529,DEC_D414,C14_PMEN_CS7,C14_PMEN_CS3,P14_RP_ACH19,P14_RP_CCCOLL,P14_ANEM_RP_PROP,P14_ACTOCC15P_ILT2,P14_RP_2P,P14_PMEN_ANEM0509,P14_RP_ACH70,P14_POP2554,P14_ACTOCC15P_ILT2P,P14_RP_M30M2,P14_RP_PROP,P14_POP15P_NONMARIEE,C14_NE24F0,C14_ACTOCC1564_CS6,P14_NPER_RP_GRAT,P14_RPAPPART_ACHTOT,P14_PMEN_ANEM10P,C14_PMEN_MENFAM,P14_NBPI_RP,P14_RP_ACH90,C14_POP15P_CS2,C14_NE24F2,C14_POP15P_CS7,C14_ACT1564_CS3,DEC_D214,P14_NSCOL15P_BAC,P14_RSECOCC,P14_RP_CINDELEC,P14_POP1524_PSEUL,P14_RP_ACH45,NB_A504,P14_POP5579,C14_PMEN_CS8,C14_PMEN_CS4,C14_ACTOCC15P,DEC_MED14,P14_ACT1524,C14_PMEN_CS2,P14_RPMAISON_ACH90,P14_NBPI_RPAPPART,P14_ANEM_RP_GRAT,P14_ANEM_RP_LOC,P14_POP30P,C14_ACTOCC15P_TCOM,P14_RP_LOC,P14_POP65P,P14_RP_ACHTOT,C14_POP15P_CS8,C14_PMEN_MENCOUPSENF,C14_ACTOCC1564_CS3,DEC_D314,P14_ACTOCC15P_TP,P14_RPAPPART_ACH90,P14_RPMAISON_ACH11,P14_POP15P,C14_PMEN_MENCOUPAENF,DEC_D714,DEC_Q314,P14_NSCOL15P,C14_MEN_CS3,C14_ACTOCC15P_VOIT,P14_RPAPPART_ACH45,P14_RP_1P,P14_CHOM2554,C14_MENSFAM,P14_RP_CCIND,P14_SAL15P,P14_RP_4060M2,P14_RPAPPART_ACH11,P14_RP_80100M2,C14_PMEN_MENSFAM,NB_B302,
3,P14_POPMEN2554,P14_ACTOCC15P_ILT3,P14_PMEN,P14_NSAL15P_INDEP,P14_RPAPPART_ACH70,P14_RP_3040M2,C14_ACT1564_CS6,P14_NBPI_RP_ANEM10P,P14_ANEM_RP,P14_RP_3P,P14_POP0610,P14_NSAL15P,AREA,P14_POP1824,P14_MEN_ANEM0002,P14_NSCOL15P_SUP,DENSITY,P14_POP0014,P14_POPMEN1524,C14_MENPSEUL,P14_POPMEN5579,P14_RPMAISON,P14_POP,C14_MENCOUPSENF,P14_MEN_ANEM0204,P14_ANEM_RP_LOCHLMV,P14_LOGVAC,DEC_D814,DEC_D914,P14_NPER_RP_PROP,P14_POP0305,P14_NSCOL15P_DIPLMIN,C14_ACTOCC15P_MAR,P14_APPART,P14_ACTOCC2554,P14_NPER_RP_LOCHLMV,P14_RP_VOIT1,P14_POP15P_MARIEE,P14_RPAPPART_ACH19,P14_POP1517,C14_POP15P_CS6,DEC_D414,P14_POP1117,P14_RP_CCCOLL,C14_PMEN_CS3,P14_RP_ACH19,P14_CHOM1524,P14_ANEM_RP_PROP,P14_SCOL2529,P14_ACTOCC15P_ILT2,P14_MAISON,C14_MEN_CS2,P14_PMEN_ANEM0509,P14_RP_ACH70,P14_RP_VOIT1P,P14_RP_2P,P14_SAL15P_CDI,P14_ACTOCC15P_ILT2P,P14_RP_M30M2,C14_PMEN_MENFAMMONO,P14_NPER_RP_GRAT,C14_ACTOCC1564_CS6,P14_POP1524,P14_RPAPPART_ACHTOT,P14_PMEN_ANEM10P,C14_ACTOCC15P_DROU,C14_PMEN_MENFAM,P14_RP_ACH90,C14_PMEN_CS6,C14_MENFSEUL,C14_ACT1564_CS3,P14_NSCOL15P_BAC,P14_ACTOCC15P_ILT1,P14_POP_IMM,P14_RSECOCC,C14_MENFAMMONO,P14_RP_CINDELEC,P14_ACTOCC1564,P14_SCOL0610,P14_NBPI_RPMAISON,P14_POP1524_PSEUL,P14_POP5579,P14_NPER_RP_LOC,C14_PMEN_CS8,C14_ACTOCC15P,DEC_MED14,P14_ACT1524,P14_RPMAISON_ACHTOT,P14_RPAPPART,P14_RPMAISON_ACH90,P14_NBPI_RPAPPART,P14_POP_ETR,P14_ACT5564,P14_ANEM_RP_GRAT,P14_NBPI_RP_ANEM0002,P14_ANEM_RP_LOC,C14_ACTOCC15P_PAS,P14_RPAPPART_ACH05,C14_ACTOCC15P_TCOM,C14_PMEN,P14_NSCOL15P_CAPBEP,C14_PMEN_MENCOUPSENF,C14_POP15P_CS8,P14_POP0205,P14_SAL15P_APPR,DEC_D714,C14_MEN_CS3,DEC_Q314,P14_PMEN_ANEM0204,P14_RP_1P,P14_RP_CCIND,P14_SAL15P,P14_RP_4060M2,C14_ACTOCC1564_CS2,C14_POP15P_CS3,C14_ACT1564_CS2,P14_NBPI_RP_ANEM0204,P14_RP_5PP
4,P14_RP_6080M2,P14_MEN_ANEM10P,P14_ACTOCC15P_ILT3,P14_PMEN,DEC_Q114,P14_RPAPPART_ACH70,P14_SCOL0205,P14_RP_3P,P14_POP0610,AREA,P14_MEN_ANEM0002,P14_NSCOL15P_SUP,P14_POP6074,DENSITY,P14_POPMEN5579,C14_NE24F4P,P14_RPMAISON,P14_POP,P14_CHOM5564,P14_SCOL1824,DEC_D614,P14_POP1564,P14_ANEM_RP_LOCHLMV,P14_RP_LOCHLMV,P14_LOGVAC,DEC_D814,DEC_D914,P14_NPER_RP_PROP,P14_NSCOL15P_DIPLMIN,C14_ACTOCC15P_MAR,P14_APPART,P14_RP_ACH05,DEC_D114,P14_ACTOCC2554,P14_NPER_RP_LOCHLMV,P14_POP15P_MARIEE,P14_RPAPPART_ACH19,DEC_D414,P14_ACTOCC15P_ILT5,P14_RP_CCCOLL,C14_PMEN_CS3,P14_RP_ACH19,P14_ANEM_RP_PROP,P14_PHORMEN,P14_SCOL2529,P14_RP_2P,P14_ACTOCC15P_ILT2,P14_PMEN_ANEM0509,P14_RP_ACH70,P14_POP6579,P14_ACTOCC15P_ILT2P,P14_RP_M30M2,P14_ACTOCC5564,P14_POP15P_NONMARIEE,P14_RPAPPART_ACHTOT,P14_PMEN_ANEM10P,P14_RP_ACH90,C14_PMEN_CS6,C14_POP15P_CS7,C14_ACT1564_CS3,P14_RP_ACH11,DEC_D214,P14_ACTOCC15P_ILT1,P14_POP_IMM,P14_RSECOCC,P14_RP_CINDELEC,C14_NE24F1,P14_NBPI_RPMAISON,P14_POP1524_PSEUL,P14_RP_ACH45,P14_NPER_RP_LOC,C14_PMEN_CS8,P14_RP_120M2P,DEC_MED14,P14_RPAPPART,P14_RPMAISON_ACH90,P14_NBPI_RPAPPART,P14_POP_ETR,P14_ANEM_RP_GRAT,P14_NBPI_RP_ANEM0002,P14_ANEM_RP_LOC,P14_RPAPPART_ACH05,C14_ACTOCC15P_TCOM,P14_RP_GARL,C14_POP15P_CS4,P14_RP_LOC,C14_ACTOCC1564_CS3,P14_RPAPPART_ACH90,DEC_D714,DEC_Q314,C14_MEN_CS3,P14_RP_GRAT,P14_RPAPPART_ACH45,P14_RP_1P,C14_MENSFAM,C14_MEN_CS8,P14_RP_4060M2,P14_RPAPPART_ACH11,P14_RP_80100M2,C14_POP15P_CS3,P14_ETUD1564,C14_PMEN_MENSFAM,P14_NBPI_RP_ANEM0204,,,,,,,,,,,,,,,
5,C14_POP15P,P14_RP_6080M2,P14_PMEN_ANEM0002,P14_MEN_ANEM10P,P14_ACTOCC15P_ILT3,DEC_Q114,P14_RPAPPART_ACH70,P14_RP_3040M2,C14_ACT1564_CS6,P14_NBPI_RP_ANEM10P,P14_ANEM_RP,P14_NSAL15P,AREA,P14_POP1824,P14_MEN_ANEM0002,DENSITY,C14_ACT1564,P14_POPMEN1524,C14_MENPSEUL,P14_POP,P14_NSAL15P_EMPLOY,P14_SCOL1824,DEC_D614,P14_MEN_ANEM0204,P14_ANEM_RP_LOCHLMV,P14_RP_LOCHLMV,P14_LOGVAC,P14_POP4054,DEC_D814,DEC_D914,P14_APPART,P14_POP1529,P14_RP_ACH05,DEC_D114,P14_NPER_RP_LOCHLMV,P14_RP_VOIT1,C14_MENHSEUL,P14_RPMAISON_ACH19,P14_POP15P_MARIEE,P14_RPAPPART_ACH19,DEC_D414,P14_RP_CCCOLL,C14_PMEN_CS3,P14_RP_ACH19,P14_CHOM1524,P14_ANEM_RP_PROP,P14_RP_2P,P14_ACTOCC15P_ILT2,C14_MEN_CS2,P14_RP_ACH70,P14_ACTOCC15P_ILT2P,P14_RP,P14_RP_M30M2,C14_PMEN_MENFAMMONO,P14_POP15P_NONMARIEE,C14_ACTOCC1564_CS6,P14_POPMEN15P,P14_PMEN_ANEM10P,C14_PMEN_MENFAM,C14_PMEN_CS6,C14_MENFSEUL,C14_ACT1564_CS3,DEC_D214,P14_ACTOCC15P_ILT1,P14_POP_IMM,P14_RSECOCC,P14_RP_CINDELEC,P14_POP4559,C14_PMEN_CS5,P14_POP1524_PSEUL,P14_RP_ACH45,P14_NPER_RP_LOC,P14_RPMAISON_ACH70,C14_PMEN_CS8,C14_PMEN_CS4,C14_ACTOCC15P,DEC_MED14,C14_MEN_CS6,P14_ACT1524,P14_RPAPPART,P14_NBPI_RPAPPART,P14_POP_ETR,P14_ANEM_RP_GRAT,P14_NBPI_RP_ANEM0002,P14_ANEM_RP_LOC,P14_RPAPPART_ACH05,P14_ACTOCC15P,C14_ACTOCC15P_TCOM,P14_RP_GARL,P14_SCOL30P,P14_POP0019,C14_POP15P_CS8,C14_ACTOCC1564_CS3,DEC_D314,P14_RPAPPART_ACH90,P14_SAL15P_APPR,DEC_D714,P14_RP_100120M2,C14_MEN_CS3,P14_NSCOL15P,DEC_Q314,C14_ACTOCC15P_VOIT,P14_RPAPPART_ACH45,P14_RP_1P,P14_RPMAISON_ACH05,C14_MENSFAM,C14_MEN_CS8,P14_RP_4060M2,P14_RPAPPART_ACH11,P14_RP_80100M2,C14_POP15P_CS3,C14_PMEN_MENSFAM,NB_B302,,,,,
#!/usr/bin/env python
# encoding: utf-8
# =============================================================================
# main.py: runs the Flask server (http://flask.pocoo.org/) using routes
# =============================================================================
import json
import logging
import os
import webbrowser
import predihood.config
import pandas as pd
from flask import Flask, flash, render_template, request, send_from_directory
from predihood import model
from predihood.classes.Data import Data
from predihood.classifiers_list import AVAILABLE_CLASSIFIERS
from predihood.config import FILE_MANUAL_ASSESSMENT_EXPERTS
from predihood.predict import compute_all_accuracies, predict_one_iris
from predihood.utility_functions import signature_of_algorithm, get_classifier, set_classifier, add_assessment_to_file
from sklearn.utils._testing import ignore_warnings
log = logging.getLogger(__name__)
app = Flask(__name__)
app.config["JSON_SORT_KEYS"] = False
url = "http://127.0.0.1:8081/"
@app.route('/', defaults={'page': None}, methods=["GET"])
def index(page):
"""
Render the main page of the interface, i.e. `cartographic-interface.html`.
Returns:
The page to display.
"""
if not model.db.connection_status: # if no connection, display a flashing message
flash("Could not connect to the MongoDB database ! Check the connection.", "danger")
if "lang" in request.args:
predihood.config.PREFERRED_LANGUAGE = request.args["lang"]
else:
predihood.config.PREFERRED_LANGUAGE = "english"
return render_template("index.html", language=predihood.config.PREFERRED_LANGUAGE)
@app.route('/cartographic-interface.html', methods=["GET"])
def get_cartographic_page():
"""
Render the page of the cartographic interface, i.e. `cartographic-interface.html`.
Returns:
The page to display.
"""
return render_template('cartographic-interface.html', language=predihood.config.PREFERRED_LANGUAGE)
@app.route('/algorithmic-interface.html', methods=["GET"])
def get_algorithms_page():
"""
Render the page of the algorithmic interface, i.e. `algorithmic-interface.html`.
Returns:
The page to display.
"""
return render_template('algorithmic-interface.html', language=predihood.config.PREFERRED_LANGUAGE)
@app.route('/details-iris.html', methods=["GET"])
def get_details_iris():
"""
Get all information about the given IRIS.
Returns:
A page that contains all information about the given IRIS (descriptive, grouped and raw indicators).
"""
code_iris = request.args['code_iris']
iris = model.get_iris_from_code(code_iris)
dict_code_label = model.parse_json_to_dict(model.json_iris_indicator_code_to_label)
if iris is None:
flash("No corresponding iris for code " + code_iris + ".", "warning")
return render_template('details-iris.html', iris=iris, dict_code_label=dict_code_label, language=predihood.config.PREFERRED_LANGUAGE)
@app.route('/getClassifiers', methods=["GET"])
def get_classifiers():
"""
Get list of available classifiers (stored in AVAILABLE_CLASSIFIERS).
Returns:
A list containing the names of the available classifiers.
"""
available_classifiers = list(AVAILABLE_CLASSIFIERS.keys())
if available_classifiers is not None:
return {"classifiers": available_classifiers}
else:
return {"error": "The list of classifiers can not be retrieved. You might reload the page."}
@app.route('/getParameters', methods=["GET"])
def get_parameters():
"""
Get parameters of the given classifier by give its name.
Returns:
A dictionary containing for each parameter its name, its types, its default value, and its definition.
"""
if 'name' in request.args:
name = request.args['name']
parameters, message = signature_of_algorithm(name)
if parameters != {} and message == "OK":
return parameters
else:
if message == "no_documentation": return "There is no documentation for the selected algorithm, therefore parameters can not be retrieved."
elif message == "no_parameters": return "There was a problem while retrieving algorithm's parameters. You can check the Python's console."
else:
return "There is no parameters to get. Be sure to select an algorithm in the list."
@app.route('/run', methods=["GET"])
@ignore_warnings(category=FutureWarning)
def run_algorithm():
"""
Run classifier on data with the specified parameters.
Returns:
The computed accuracies for each EV and each list. The top-k are also returned.
"""
# 1. get parameters specified by the user
clf_name = request.args['clf']
parameters = json.loads(request.args['parameters'])
train_size = parameters["train_size"]
test_size = parameters["test_size"]
remove_outliers = parameters["remove_outliers"]
remove_rural = parameters["remove_rural"]
add_manual_assessment = parameters["add_manual_iris"]
# 2. create an instance of the given classifier and tune it with user's parameters
clf = get_classifier(clf_name)
clf = set_classifier(clf, parameters)
# 3. run experiment on data to get accuracies for each EV and each list of selected indicators
data = Data(normalization="density", filtering=True, add_assessment=add_manual_assessment)
data.init_all_in_one()
accuracies, message = compute_all_accuracies(data, clf, train_size, test_size, remove_outliers, remove_rural)
return {"results": accuracies, "tops_k": predihood.config.TOPS_K, "message": message}
@app.route('/predict_iris', methods=["GET"])
def predict_iris():
"""
Predict the environment (i.e. 6 EV) of the given IRIS.
Returns:
Predictions for each EV
"""
iris_code_to_predict = request.args['iris_code']
clf_name = request.args['algorithm_name']
clf = get_classifier(clf_name)
data = Data(normalization="density", filtering=True)
data.init_all_in_one()
predictions, message = predict_one_iris(iris_code_to_predict, data, clf, 0.8, 0.2, False) # clf
return {"predictions": predictions, "message": message}
@app.route('/getIrisPolygon', methods=["GET"])
def get_iris_for_polygon():
"""
Get the list of IRIS in the given polygon. The polygon is defined by two points given in the AJAX request.
Returns:
A list of the IRIS that are in the given polygon.
"""
lat1 = float(request.args['lat1'])
lng1 = float(request.args['lng1'])
lat2 = float(request.args['lat2'])
lng2 = float(request.args['lng2'])
iris = model.get_iris_for_polygon(lat1, lng1, lat2, lng2)
if iris is None or len(iris) == 0:
flash("No iris found in the area.", "warning")
else:
flash(str(len(iris)) + " iris found in the area.", "success")
return json.dumps({'status': 'OK', 'geojson': iris})
@app.route('/countIrisPolygon', methods=["GET"])
def count_iris_for_polygon():
"""
Count the number of IRIS in the given polygon. The polygon is defined by two points given in the AJAX request.
Returns:
The number of IRIS that are in the given polygon.
"""
lat1 = float(request.args['lat1'])
lng1 = float(request.args['lng1'])
lat2 = float(request.args['lat2'])
lng2 = float(request.args['lng2'])
nb_iris = model.count_iris_for_polygon(lat1, lng1, lat2, lng2)
return json.dumps({'status': 'OK', 'nbIris': nb_iris})
@app.route('/searchCode', methods=["GET"])
def get_iris_from_code():
"""
Get an IRIS object (represented by a dictionary) given its code. The code is a string of 9 digits.
Returns:
An object that represents the IRIS corresponding to the given code.
"""
code_iris = request.args['codeIris']
iris = model.get_iris_from_code(code_iris)
if iris is None:
flash("No corresponding iris for code " + code_iris + ".", "warning")
else:
flash("Found iris " + code_iris + ".", "success")
return json.dumps({'status': 'OK', 'geojson': iris})
@app.route('/searchName', methods=["GET"])
def get_iris_from_name():
"""
Get IRIS given its name. The search is done on IRIS's name and IRIS' city.
Returns:
A list of IRIS corresponding to the given name.
"""
query = request.args['querySearch']
iris = model.get_iris_from_name(query)
if iris is None or len(iris) == 0:
if predihood.config.PREFERRED_LANGUAGE == "french":
flash("Pas d'IRIS pour la requête " + query + ".", "warning")
else:
flash("No corresponding iris for query " + query + ".", "warning")
else:
if predihood.config.PREFERRED_LANGUAGE == "french":
flash(str(len(iris)) + " iris trouvés pour la requête " + query + ".", "success")
else:
flash(str(len(iris)) + " iris found for query " + query + ".", "success")
return json.dumps({'status': 'OK', 'geojson': iris})
@app.route('/getEnvironmentValues', methods=["GET"])
def get_environment_values():
variables_with_values = {}
if predihood.config.PREFERRED_LANGUAGE == "french":
for env in predihood.config.ENVIRONMENT_VALUES:
temp = []
for key in predihood.config.ENVIRONMENT_VALUES[env]:
temp.append(key) # get french values
variables_with_values[env] = temp
else:
for env in predihood.config.ENVIRONMENT_VALUES:
temp = []
for key in predihood.config.ENVIRONMENT_VALUES[env]:
temp.append(predihood.config.ENVIRONMENT_VALUES[env][key]) # get english values
variables_with_values[env] = temp
return json.dumps(variables_with_values) # {"result": variables_with_values}
@app.route('/add_iris_to_csv', methods=["GET"])
def add_iris_to_csv():
"""
Adds an assessed IRIS to a CSV file. Not available in production mode.
Returns:
A message that explain the status of the request, i.e. OK if the IRIS has been added, KO else.
"""
assessed_values = []
for env in predihood.config.ENVIRONMENT_VALUES:
assessed_values.append(request.args[env])
message = add_assessment_to_file(request.args['code_iris'], assessed_values)
return json.dumps({"status": message})
@app.route("/add_iris_file", methods=["GET"])
def add_iris_file():
assessed_iris_file = pd.read_csv(FILE_MANUAL_ASSESSMENT_EXPERTS)
for index, row in assessed_iris_file.iterrows():
code_iris = str(row["code"]) if len(str(row["code"])) == 9 else "0"+str(row["code"])
assessed_values = []
for env in predihood.config.ENVIRONMENT_VALUES:
assessed_values.append(row[env])
add_assessment_to_file(code_iris, assessed_values)
return json.dumps({"status": "Your IRIS have been added."})
@app.route("/get_preferred_language", methods=["GET"])
def get_preferred_language():
return json.dumps({"preferred_language": predihood.config.PREFERRED_LANGUAGE})
@app.route('/favicon.ico')
@app.route('/<page>/favicon.ico')
def favicon():
"""
Display the favicon.
Returns:
The favicon.
"""
return send_from_directory(os.path.join(app.root_path, 'static'), 'favicon.png', mimetype='image/favicon.png')
if __name__ == '__main__':
webbrowser.open_new(url)
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0 # do not cache files, especially static files such as JS
app.secret_key = 's3k_5Et#fL45k_#ranD0m-(StuF7)'
app.run(port=8081) # debug=True
import logging
import predihood.config
from collections import OrderedDict
from predihood.classes.Data import Data
from predihood.classes.Dataset import Dataset
from predihood.classes.MethodPrediction import MethodPrediction
from predihood.config import ENVIRONMENT_VARIABLES, TRAIN_SIZE, TEST_SIZE, ENVIRONMENT_VALUES, ENVIRONMENT_VARIABLES_FR
from predihood.selection import retrieve_lists
from predihood.utility_functions import check_train_test_percentages, get_most_frequent
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
from sklearn.exceptions import ConvergenceWarning
from sklearn.linear_model import LogisticRegression, SGDClassifier
from sklearn.neighbors import KNeighborsClassifier, NearestCentroid
from sklearn.svm import SVC
from sklearn.utils._testing import ignore_warnings
log = logging.getLogger(__name__)
# define classifiers used in the experimental validation
CLASSIFIERS = [
LogisticRegression(penalty="l2"),
KNeighborsClassifier(n_neighbors=30),
RandomForestClassifier(n_estimators=300),
SVC(kernel="rbf"),
SGDClassifier(),
NearestCentroid(),
AdaBoostClassifier()
]
@ignore_warnings(category=ConvergenceWarning)
def compute_all_accuracies(data, clf, train_size, test_size, remove_outliers=False, remove_rural=False):
"""
Compute accuracies for each EV and each list with the given classifier.
Args:
data: a Data object that contains assessed IRIS and their attributes
clf: an object which is a classifier (with `fit` and `predict` methods)
train_size: an integer corresponding to the size of the training sample
test_size: an integer corresponding to the size of the test sample
remove_outliers: True to remove from the dataset IRIS that are detected as outliers, False else
remove_rural: True to remove IRIS that are in the countryside to avoid bias while predicting, False else
Returns:
a dictionary of results for each EV and each list of selected indicators
"""
log.info("... Computing accuracies ...")
train_size, test_size, message = check_train_test_percentages(train_size, test_size)
data_not_filtered = Data(normalization="density", filtering=False, add_assessment=data.add_assessment)
data_not_filtered.init_all_in_one()
lists = retrieve_lists(add_assessment=data.add_assessment)
results = {}
for j, env in enumerate(ENVIRONMENT_VARIABLES):
if predihood.config.PREFERRED_LANGUAGE == "french":
results[ENVIRONMENT_VARIABLES_FR[env]] = OrderedDict()
else:
results[env] = OrderedDict()
log.debug("--- %s ---", env)
dataset = Dataset(data_not_filtered, env, selected_indicators=data_not_filtered.indicators, train_size=train_size, test_size=test_size, outliers=remove_outliers, remove_rural=remove_rural, _type='supervised')
dataset.init_all_in_one()
# if remove_rural: dataset.remove_rural_iris()
mean_classifier = 0.0
algo = MethodPrediction(name="", dataset=dataset, classifier=clf)
algo.fit()
algo.compute_performance()
if predihood.config.PREFERRED_LANGUAGE == "french":
results[ENVIRONMENT_VARIABLES_FR[env]]["accuracy_none"] = algo.accuracy
results[ENVIRONMENT_VARIABLES_FR[env]]["accuracies"] = OrderedDict()
else:
results[env]["accuracy_none"] = algo.accuracy
results[env]["accuracies"] = OrderedDict()
log.info("accuracy for %s without filtering: %f", env, algo.accuracy)
for top_k, lst in lists.items():
dataset = Dataset(data, env, selected_indicators=lst[env], train_size=train_size, test_size=test_size, outliers=remove_outliers, remove_rural=remove_rural, _type='supervised')
dataset.init_all_in_one()
# if remove_rural: dataset.remove_rural_iris()
algo2 = MethodPrediction(name='', dataset=dataset, classifier=clf)
algo2.fit()
algo2.compute_performance()
mean_classifier += algo2.accuracy
if predihood.config.PREFERRED_LANGUAGE == "french":
results[ENVIRONMENT_VARIABLES_FR[env]]["accuracies"][str(top_k)] = algo2.accuracy
else:
results[env]["accuracies"][str(top_k)] = algo2.accuracy
log.info("accuracy for %s with %s: %f", env, top_k, algo2.accuracy)
mean_classifier /= len(CLASSIFIERS)
if predihood.config.PREFERRED_LANGUAGE == "french":
results[ENVIRONMENT_VARIABLES_FR[env]]["mean"] = mean_classifier
else:
results[env]["mean"] = mean_classifier
log.info("mean for classifier: %f", mean_classifier)
results = OrderedDict(results)
log.info(results)
return results, message
def predict_one_iris(iris_code, data, clf, train_size, test_size, remove_outliers=False):
"""
Predict the 6 EV for the given IRIS, the given data and the given classifier.
Args:
iris_code: a string that contains the code of the IRIS (9 digits)
data: a Data object on which classifier will learn
clf: an object (classifier) to perform the prediction
train_size: an integer corresponding to the size of the train sample
test_size: an integer corresponding to the size of the test sample
remove_outliers: True to remove from the dataset IRIS that are detected as outliers, False else
Returns:
A dictionary containing predictions for each EV.
"""
train_size, test_size, message = check_train_test_percentages(train_size, test_size)
lists = retrieve_lists()
predictions = {}
for j, env in enumerate(ENVIRONMENT_VARIABLES):
log.info("predicting for %s", env)
predictions_lst = []
for top_k, lst in lists.items():
dataset = Dataset(data, env, selected_indicators=lst[env], train_size=train_size, test_size=test_size, outliers=remove_outliers, _type="supervised")
dataset.init_all_in_one()
algorithm = MethodPrediction(name='', dataset=dataset, classifier=clf)
algorithm.fit()
algorithm.predict(iris_code)
if predihood.config.PREFERRED_LANGUAGE == "french":
predicted_value = list(ENVIRONMENT_VALUES[env].keys())[list(ENVIRONMENT_VALUES[env].values()).index(algorithm.prediction)] # get french translation of the predicted value
else:
predicted_value = algorithm.prediction
predictions_lst.append(predicted_value)
if predihood.config.PREFERRED_LANGUAGE == "french":
predictions[ENVIRONMENT_VARIABLES_FR[env]] = get_most_frequent(predictions_lst)
else:
predictions[env] = get_most_frequent(predictions_lst) # get the most frequent value and the number of occurrences
print(predictions) # {'building_type': {'most_frequent': 'Towers', 'count_frequent': 7}, 'building_usage': {'most_frequent': 'Housing', 'count_frequent': 4}, ... }
return predictions, message
if __name__ == '__main__':
# Create data
data = Data(normalization="population", filtering=True)
data.init_all_in_one()
# Compute accuracies for each EV and each top-k
compute_all_accuracies(data, RandomForestClassifier(), TRAIN_SIZE, TEST_SIZE)
# Predict EV of the "Part-Dieu" IRIS, which is he CBD of Lyon (Central Business District)
predict_one_iris("693830301", data, RandomForestClassifier(), TRAIN_SIZE, TEST_SIZE)
import json
import logging
import numpy as np
import os
import pandas as pd
from predihood.classes.Data import Data
from predihood.classes.Dataset import Dataset
from predihood.classes.MethodSelection import MethodSelection
from predihood.config import TOPS_K, ENVIRONMENT_VARIABLES, FOLDER_SELECTED_INDICATORS, FILE_HIERARCHY
from predihood.utility_functions import apply_hierarchy
from sklearn.ensemble import RandomForestClassifier, ExtraTreesClassifier
log = logging.getLogger(__name__)
def generate_all_data():
"""
Generate all datasets, i.e. one with density normalization, one for population normalization and one without normalization.
The three are filtered. Generated datasets are located in generated_files/datasets.
"""
data = Data(normalization="density", filtering=True)
data.init_all_in_one()
data = Data(normalization="population", filtering=True)
data.init_all_in_one()
data = Data(normalization=None, filtering=True)
data.init_all_in_one()
def retrieve_lists(add_assessment=False, top_k=None):
"""
Get all lists generated for each top-k or for the given top-k if provided.
Args:
top_k: a integer corresponding to the top-k of the list to retrieve
Returns:
a dictionary containing the lists of indicators for each top-k
"""
lists = {}
if top_k:
# a top-k is specified, so the list of indicators of size top-k is retrieved
lst = retrieve_one_list(add_assessment, top_k)
lists[str(top_k)] = lst
else:
# no top-k is provided, so all lists form 10 to 100 indicators are retrieved
for top_k in TOPS_K:
lst = retrieve_one_list(add_assessment, top_k)
lists[str(top_k)] = lst
return lists
def retrieve_one_list(add_assessment, top_k):
"""
Retrieve the list of selected INSEE indicators corresponding to the given top-k.
Args:
top_k: an integer corresponding to the size of the list to retrieve
Returns:
a list containing indicators of the list of size top-k
"""
if not os.path.exists(os.path.join(FOLDER_SELECTED_INDICATORS, "list" + str(top_k) + ".csv")): generate_lists(add_assessment)
indicators_csv = pd.read_csv(os.path.join(FOLDER_SELECTED_INDICATORS, "list" + str(top_k) + ".csv"), header=None)
lst = json.loads(indicators_csv.drop(indicators_csv.columns[0], axis=1).to_json(orient="index"))
list_temp = {}
for key, value in lst.items():
list_temp[ENVIRONMENT_VARIABLES[int(key)]] = [value2 for key2, value2 in value.items() if value2 is not None]
return list_temp
def generate_lists(add_assessment=False):
"""
Generates lists of INSEE indicators that are relevant for prediction.
This selection process is based on:
- removing fully correlated indicators
- select a limited number among the most relevant indicators (using Random Forest and Extra Tree classifiers)
- taking into account the diversity of categories of INSEE indicators based on a hierarchy of these indicators
"""
# 1. Create data
data = Data(normalization="density", filtering=True, add_assessment=add_assessment)
data.init_all_in_one()
# 2. Run heat map and get fully correlated indicators by using a correlation matrix
dataset = Dataset(data, "building_type", "unsupervised")
dataset.init_all_in_one()
heat_map = MethodSelection(name="heat map", dataset=dataset, parameters={"method": "spearman"})
heat_map.compute_selection()
fully_correlated_indicators = heat_map.best_indicators
log.info("fully correlated indicators: %d %s", len(fully_correlated_indicators), ", ".join(fully_correlated_indicators))
# 3. Select a limited number (top-k) of indicators by using Random Forest and Extra Tree classifiers.
# Then take into account the diversity of indicators by using a hierarchy of the INSEE indicators
hierarchy = pd.read_csv(FILE_HIERARCHY, sep="\t")
# 4. For each size of list (i.e. for each top-k), select a limited number of indicators with Extra Tree and Random Forest classifiers
# Then merge the two results to obtain a single list of relevant indicators.
for top_k in TOPS_K:
log.info("constructing list of %d indicators", top_k)
all_lists = [] # to keep lists of indicators for each EV (for the current top-k)
for env in ENVIRONMENT_VARIABLES:
dataset = Dataset(data, env, indicators_to_remove=fully_correlated_indicators, _type="supervised")
dataset.init_all_in_one()
# a. get best indicators according to Extra Tree classifier
fi_et = MethodSelection(name="feature importance ET", dataset=dataset, classifier=ExtraTreesClassifier(), parameters={"top_k": top_k})
fi_et.fit()
fi_et.compute_selection()
best_indicators_ET = fi_et.best_indicators
# b. get best indicators according to Random Forest classifier
fi_rf = MethodSelection(name="feature importance RF", dataset=dataset, classifier=RandomForestClassifier(), parameters={"top_k": top_k})
fi_rf.fit()
fi_rf.compute_selection()
best_indicators_RF = fi_rf.best_indicators
# c. merge indicators that have been selected by ET and RF classifiers
# in this step, if an indicator have been selected by the two classifiers, its score is the addition of its score for RF and the one for ET.
best_indicators_ET.extend(best_indicators_RF)
all_selected_indicators = best_indicators_ET # all selected indicators, i.e. union between RF and ET
keys = set([element[0] for element in all_selected_indicators]) # store indicators' names selected
merged_indicators_temp = {key: 0 for key in keys}
for i in range(len(all_selected_indicators)):
indicator = all_selected_indicators[i]
merged_indicators_temp[indicator[0]] += indicator[1] # adding score
# transform it into a list of sub-lists, e.g. [[indicator1, score1], ..., indicatorN, scoreN]]
merged_indicators = [[key, merged_indicators_temp[key]] for key in merged_indicators_temp]
# d. apply hierarchy on selected indicators to taking into account the diversity of categories of indicators
indicators_hierarchy = apply_hierarchy(merged_indicators, hierarchy)
# get the names of each selected indicator
selected_indicators_names = [indicator[0] for indicator in indicators_hierarchy]
# e. add uncorrelated indicators of heat map to the lists
all_lists.append(selected_indicators_names)
# C. Transform lists of selected indicators for the current top-k and save it as a CSV file
# indexes = {i: ENVIRONMENT_VARIABLES[i] for i in range(len(ENVIRONMENT_VARIABLES))}
selected_indicators = pd.DataFrame(np.array(all_lists).tolist())
selected_indicators.to_csv(os.path.join(FOLDER_SELECTED_INDICATORS, "list"+str(top_k)+".csv"), header=False)
if __name__ == "__main__":
generate_all_data()
generate_lists()
let classifiers = getClassifiers();
addClassifiers();
let current_parameters = null; // parameters' dict from server
let generalParameters = ["class_weight", "cv", "kernel", "max_iter", "memory", "metric", "n_components", "n_jobs", "pos_label", "random_state", "scoring", "verbose", "warm_start"]; // parameters that are not specific to classifiers
let trainPercentage = $("#trainPercentage").val(); // to update test percentage depending on train percentage
let testPercentage = $("#testPercentage").val(); // to update train percentage depending on test percentage
let request_run = null; // the request send to the server (with classifier and its parameters)
const MAX_PARAMETERS = 2;
let preferred_language_algo = get_preferred_language();
// get parameters of the selected classifier and display them in the interface.
$("#selectAlgorithm").change(function () {
let algorithm_name = $(this).children("option:selected").val();
getParameters(algorithm_name);
$("#tuningSection").css("visibility", "visible");
});
// update up/down symbols when hide or show parameters in the tuning section.
for (let param_section of ["#specificParameters", "#commonParameters"]) {
$(param_section + "Title").on("click", function () {
if ($(param_section).css("display") === "none") {
$(param_section).css("display", "block");
$(param_section + "Title").addClass("fa-angle-double-up").removeClass("fa-angle-double-down");
} else if ($(param_section).css("display") === "block") {
$(param_section).css("display", "none");
$(param_section + "Title").addClass("fa-angle-double-down").removeClass("fa-angle-double-up");
}
});
}
// test percentage input is updated when train input is changed
$("#trainPercentage")
.change(function () {
let difference = parseInt(trainPercentage) - parseInt($(this).val());
let value_test = parseInt($("#testPercentage").val()) + difference;
$("#testPercentage").val(value_test);
trainPercentage = $("#trainPercentage").val();
testPercentage = $("#testPercentage").val();
})
.on("click", function (event) {
event.preventDefault();
}); // prevent user from clicking on the input
// train percentage input is updated when test input is changed
$("#testPercentage")
.change(function () {
let difference = parseInt(testPercentage) - parseInt($(this).val());
let value_train = parseInt($("#trainPercentage").val()) + difference;
$("#trainPercentage").val(value_train);
trainPercentage = $("#trainPercentage").val();
testPercentage = $("#testPercentage").val();
})
.on("click", function (event) {
event.preventDefault();
}); // prevent user from clicking on the input
// run the classifier with specified parameters and display results in the results section.
$("#runBtn").click("on", function () {
// $("body").css("cursor", "progress");
// $("html,body").css("cursor", "progress");
document.body.style.cursor = 'wait';
$(".wrapperTable input[type='checkbox']:not(:checked)").each(function () {
$(this).parent().parent().empty(); // remove tables that are not checked in the interface
});
let userParameters = {};
let chosen_clf = $("#formAlgorithm")[0].elements[0].value;
for (let key in $("#formParameters")[0].elements) {
let elem = $("#formParameters")[0].elements[key];
if (parseInt(key) === undefined || isNaN(parseInt(key))) {
continue;
} // key is not an element of the form
// console.log(elem.title + " : " + elem.value + " / " + current_parameters[elem.title]["default"]);
if (elem.value !== current_parameters[elem.title]["default"] && elem.value !== "") { // get only parameters filled by user
let label_name = elem.title;
let val = elem.value;
if (elem.type === "text") { // input with text type
if (elem.title.includes("int") && parseInt(elem.value)) {
val = parseInt(elem.value)
} else if (elem.title.includes("float") && parseFloat(elem.val)) {
val = parseFloat(elem.value)
}
userParameters[label_name] = val;
} else if (elem.type === "number") { // input with number type
userParameters[label_name] = parseFloat(elem.value);
} else if (elem.type === "checkbox") { // input with checkbox type
userParameters[label_name] = elem.checked;
}
}
}
userParameters["train_size"] = $("#trainPercentage")[0].valueAsNumber;
userParameters["test_size"] = $("#testPercentage")[0].valueAsNumber;
userParameters["remove_outliers"] = $("#removeOutliers").prop("checked");
userParameters["remove_rural"] = $("#removeRural").prop("checked");
userParameters["add_manual_iris"] = false; // $("#addAssessmentIris").prop("checked");
console.log(chosen_clf);
console.log(userParameters);
request_run = $.ajax({
"type": "GET",
"url": "/run",
//"async": false,
data: {
"clf": chosen_clf,
"parameters": JSON.stringify(userParameters)
},
success: function (result) {
// each result is displayed with :
// - a checkbox to keep the results available in the next run
// - the results table, highlighted cells are best means for each EV
// - the list of parameters associated to the results
// - the mean for this classifier (all EV combined)
if(result["message"] === "KO") { alert("Your train_size or test_size parameter was set badly. The algorithm has been run with default parameters which are 80% for train_size and 20% for test_size.") }
let keep = $("<label class='h5'><input type='checkbox' style='margin-right: 1rem;'/>" + chosen_clf + "</label>");
let table = $("<table id='tableToExport'>")
.addClass("table table-hover table-responsive")
.append($("<tbody>"));
let results = result["results"]
// header of table: None, 10, 20, ..., 100, Mean
let header = $("<tr>")
header.append("<th></th>");
if(preferred_language_algo === "french") {
header.append("<th title='Précision obtenue avec tous les indicateurs'><i>I</i></th>")
for (let key of result["tops_k"]) { header.append("<th title='Précision obtenue avec la liste de "+key+" indicateurs'>" + key + "</th>") } // adding header with tops-k
header.append("<th title=\"Précision moyenne obtenue pour la variable d'environnement\">Moyenne</th>")
} else {
header.append("<th title='Accuracy obtained with all indicators'>I</th>")
for (let key of result["tops_k"]) { header.append("<th title='Accuracy obtained by list with "+key+" indicators'>" + key + "</th>") } // adding header with tops-k
header.append("<th title='Mean accuracy for the environment variable'>Mean</th>")
}
table.append(header);
console.log(results)
// content of table with computed accuracies
for (let key in results) { // iterating over env variables
let row = $("<tr>");
let env = results[key];
let max = getMaxValueDict(results[key]["accuracies"], env["accuracy_none"]);
row.append("<td>" + capitalizeFirstLetter(key.split("_").join(" ")) + "</td>")
let col = $("<td>").text(env["accuracy_none"].toFixed(2) + "%")
if (env["accuracy_none"] === max) {
col.css("background-color", "#71dd8a")
}
row.append(col);
for (let top_k in env["accuracies"]) { // iterating over top-k for each EV
let col = $("<td>").text(env["accuracies"][top_k].toFixed(2) + "%");
if (env["accuracies"][top_k] === max) {
col.css("background-color", "#71dd8a");
}
row.append(col);
}
row.append("<td>" + env["mean"].toFixed(2) + "%</td>");
table.append(row)
}
// download icon
let download;
if(preferred_language_algo === "french") {
download = $("<i class='fas fa-download' style='margin-left: 1rem;' title='Exporter cette table comme un fichier Excel.'></i>")
} else {
download = $("<i class='fas fa-download' style='margin-left: 1rem;' title='Export this table as an Excel file.'></i>")
}
download.on("click", function (e) {
e.preventDefault();
$("#tableToExport").table2excel({
type: 'xls',
filename: chosen_clf + '.xls',
preserveColors: true
});
});
let containing_table = $("<div>").prop("class", "wrapperTable");
containing_table.append(keep).append(download).append(table);
// list of parameters used to have the current results
let params = "";
for (let elem in current_parameters) {
if (elem in userParameters) {
params += "<i>" + elem + "</i>: " + userParameters[elem] + " ; "; // adding user value
} else {
params += "<i>" + elem + "</i>: " + current_parameters[elem]["default"] + " ; ";
} // adding default value
}
containing_table.append(params);
// Mean accuracy for this classifier
let mean_clf = 0;
for (let env in results) {
mean_clf += results[env]["mean"];
}
mean_clf /= Object.keys(results).length;
if(preferred_language_algo === "french") {
containing_table.append("<br/> <b>Moyenne de cet algorithme : </b>" + mean_clf.toFixed(2) + "%");
} else {
containing_table.append("<br/> <b>Mean for this classifier: </b>" + mean_clf.toFixed(2) + "%");
}
// append all to HTML
$("#resultsDiv").append(containing_table);
document.body.style.cursor = 'default';
},
error: function (result, textStatus, errorThrown) {
console.log(errorThrown);
alert("Something went wrong while training. Please check your parameters." + textStatus);
document.body.style.cursor = 'default';
}
});
return false; // do not reload
});
// empty results when clicking on the trash icon
$("#clearResults").on("click", function () {
// empty div and add title + "clear all" button
$("#resultsDiv")
.empty()
.append("<h2 title='Results of the tuned classifier'>Results<i class='far fa-trash-alt' id='clearResults' title='Clear all results' style='color: red; font-size: 22px; padding-left: 0.5rem' ></i></h2>");
});
/**
* Adds the parameter in the interface, with label and input.
* @param {string} label The name of the parameter.
* @param {string} content The value of the parameter (default value).
* @param {string} type The type of the input (i.e. str, int, float, bool or None).
* @param {string} description The description of the parameter. It corresponds to the first sentence in the doc (sklearn) for the parameter.
* @param {boolean} hidden A boolean that indicates if the field is hidden or not (because we display only 5 parameters by default).
*/
function addElement(label, content, type, description, hidden) {
// adds something like :
// <li class="nav-item">
// <div class="nav-link">
// <i class="fa fa-question-circle mr-3 text-primary fa-fw"></i>
// parameter
// <input type="text" placeholder="">
// </div>
// </li>
let element_parameter = $("<li>").addClass("nav-item");
let div_parameter = $("<div>").addClass("nav-link")
.append("<i class='fa fas fa-question-circle mr-3 text-primary fa-fw' title='" + type + "'></i>")
.append(label)
.prop("title", description);
let input;
if (content === "None" || type.includes("str")) {
input = $("<input>")
.attr('placeholder', content);
} else {
if (type.includes("int")) {
// INT VALUE -> RANGE
let int_value = parseInt(content)
input = $("<input>")
.val(int_value)
.attr('type', 'number')
.attr('min', 0)
.attr('step', 1);
if (label === "max_iter") {
input.attr('min', -1); // specific case for max_iter parameter
}
} else if (type.includes("float")) {
// FLOAT VALUE -> RANGE
let float_value = parseFloatComplex(content);
input = $("<input>")
.val(float_value)
.attr('type', 'number')
.attr('min', float_value)
.attr('step', (float_value === 0.0 || float_value === "0.0") ? (0.1) : (float_value)); // step is the default value
} else if (type.includes("bool")) {
// BOOLEAN VALUE -> CHECKBOX
if (content === "True") {
input = $("<input>").attr('type', 'checkbox').prop("checked", true);
} else {
input = $("<input>").attr('type', 'checkbox');
}
} else {
// DEFAULT CASE -> INPUT
input = $("<input>")
.attr('placeholder', content);
}
}
input.attr('title', label);
div_parameter.append("<br>").append(input);
let rowClass = (hidden === true) ? "row hiddenParam" : "row";
element_parameter.append(div_parameter).addClass(rowClass);
generalParameters.includes(label) ? $("#commonParameters").append(element_parameter) : $("#specificParameters").append(element_parameter); // append row to the right div
hidden ? element_parameter.hide() : element_parameter.show(); // display or not the row
}
/**
* Adds all parameters that are in jsonData parameter by adding a div for the label and one for the input.
* @param{json} jsonData the dictionary with all parameters to add in the interface.
*/
function addParameters(jsonData) {
$("#specificParameters").empty(); // empty div before adding new labels and inputs
$("#commonParameters").empty();
let stepCommon = 0;
let stepSpecific = 0;
for (let element in jsonData) {
if (generalParameters.includes(element)) {
addElement(element, jsonData[element]["default"], jsonData[element]["types"], jsonData[element]["description"], (stepCommon > MAX_PARAMETERS));
stepCommon++;
} else {
addElement(element, jsonData[element]["default"], jsonData[element]["types"], jsonData[element]["description"], (stepSpecific > MAX_PARAMETERS));
stepSpecific++;
}
}
addShowMoreLess();
}
/**
* Adds a "show more" or "show less" link in the classifier's parameters section.
*/
function addShowMoreLess() {
let link_show_more = $("<a>").attr("id", "showMoreLessParams").attr("class", "seeMore").attr("href", "#")
if(preferred_language_algo === "french") {
link_show_more.text("Afficher plus...").attr("title", "Afficher plus de paramètres")
} else {
link_show_more.text("Show more...").attr("title", "Show more parameters")
}
$("#specificParameters").append(link_show_more);
$('#showMoreLessParams').click(function () {
$(this).toggleClass('seeMore');
if ($(this).hasClass('seeMore')) {
if(preferred_language_algo === "french") {
$(this).text('Afficher plus').attr("title", "Afficher plus de paramètres");
} else {
$(this).text('Show more').attr("title", "Show more parameters");
}
$("#specificParameters li.hiddenParam").each(function () {
$(this).hide(); // hide other parameters
});
} else {
if(preferred_language_algo === "french") {
$(this).text('Afficher moins').attr("title", "Afficher moins de paramètres");
} else {
$(this).text('Show less').attr("title", "Show less parameters");
}
$("#specificParameters li.hiddenParam").each(function () {
$(this).show(); // show all parameters
});
}
});
}
/**
* Add all classifiers in the select.
*/
function addClassifiers() {
for (let classifier of classifiers) {
let option = "<option>" + classifier + "</option>";
$("#selectAlgorithm").append(option);
}
}
/**
* Get parameters for the given algorithm.
* @param {string} name The name if the selected algorithm.
*/
function getParameters(name) {
$.ajax({
type: "GET",
url: "/getParameters",
data: {
'name': name
},
contentType: 'application/json;charset=UTF-8',
success: function (result) {
if(result instanceof String) {
alert(result)
} else {
current_parameters = result; // store current parameters (for the chosen classifier) in a global variable
let parameters = result;
console.log(parameters)
if (Object.keys(parameters).length > 0) {
// at least one key
addParameters(parameters);
} else {
// nothing to append, empty the div (no selection)
$("#tuningSection").css("visibility", "hidden");
}
}
},
error: function (result, textStatus, errorThrown) {
console.log(errorThrown);
}
});
}
/**
* Get the list of available classifiers, available in AVAILABLE_CLASSIFIERS (in config.py).
* @returns {[]} a list containing the names of available classifiers.
*/
function getClassifiers() {
let classifiers = [];
$.ajax({
"type": "GET",
"url": "/getClassifiers",
"async": false,
contentType: 'application/json;charset=UTF-8',
success: function (result) {
classifiers = result["classifiers"];
},
error: function (result, textStatus, errorThrown) {
console.log(errorThrown)
}
});
console.log(classifiers)
return classifiers;
}
/*
* Functions for Leaflet.js cartographic library (init Leaflet map, load a GeoJSON file as a layer, etc.)
*/
// parameters
const ZOOM_SNAP = 0.5; // step value for which the zoom increases/decreases (0.5 for finer tuning, else 1.0)
const DEFAULT_ZOOM_LEVEL_MIN_FOR_DISPLAY = 12; // zoom level above which iris are displayed (default 12)
const NB_IRIS_MAX_FOR_DISPLAY = 250; // max number of iris iris to enable display (default 250) - not used, the costly
// operation is to extract iris (>500) from database, not the display or json parsing
// global variables
let map = null; // leaflet map
let baseLayers = null; // array of basic layers
let overlayLayers = null; // array of overlaying layers
let osmLayer = null; // openstreetmap basic layer
let irisLayer = null; // layer of displayed IRIS
let previously_selected_algorithm = null;
let environment_variables = getEnvironmentVariables(); // get the json corresponding to the list of environment variables with the possible values
let preferred_language_carto = get_preferred_language(); // get the language chosen in index.html
/**
* Initialize the map
*/
function initialize() {
// creation of the map and general settings : option zoom snap degree, centering, zoom level
map = L.map("map-id", {zoomSnap: ZOOM_SNAP}).setView([46.895143, 2.397461], 6);
// creation of an OSM layer
osmLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
"attribution": 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
"maxZoom": 18,
"detectRetina": false,
"minZoom": 1,
"noWrap": false,
"subdomains": "abc"
}).addTo(map);
// legend for layers
baseLayers = {'OpenStreetMap' : osmLayer};
// add the zoom change event
map.addEventListener("zoomend", zoomendEvent);
}
/**
* Event for zoom changes : updates a label and if zoom enabled and above min zoom level, display iris
*/
function zoomendEvent() {
zoomLevel = map.getZoom();
document.getElementById("spanZoomLevel").innerHTML = zoomLevel;
isZoomDisabled = $("#inputZoomLevel").prop("disabled");
if(!isZoomDisabled) { // display after zoomend is enabled
let minZoomLevel = $("#inputZoomLevel").val();
if(zoomLevel >= minZoomLevel) { // display iris on the selected zone
bounds = map.getBounds();
iris = getIrisForBounds(bounds);
}
}
}
/**
* Method for deleting a layer (e.g., all iris in irisLayer)
*/
function removeLayer() {
map.removeLayer(irisLayer);
irisLayer = null;
$("#zoneMessages").html("");
}
/**
* Display popup with several information about the neighbourhood (descriptive information and environment variables) when clicking on it.
* @param e the event corresponding to the click.
*/
function displayPopup(e) {
var layer = e.target;
var code_iris = layer.feature.properties.CODE_IRIS
let selected_algorithm = $("#selectAlgorithmTooltip option:selected").val();
let predictions = undefined;
// common part of the popup
let divInformation = $("<div>");
let download;
if(preferred_language_carto === "french") {
download = $("<i class='fas fa-download' style='margin-left: 1rem;' title='Exporter cette table comme un fichier Excel.'></i>");
divInformation
.append("CODE IRIS : " + code_iris).append($("<br>"))
.append("IRIS : " + layer.feature.properties.NOM_IRIS).append($("<br>"))
.append("COMMUNE : " + layer.feature.properties.NOM_COM).append($("<br>"))
let moreInfosLink = $("<a>");
moreInfosLink
.prop("href", "details-iris.html?code_iris="+code_iris)
.prop("target", "_blank")
.text("Plus de détails")
.append($("<br>"));
divInformation.append(moreInfosLink).append(download);
} else {
download = $("<i class='fas fa-download' style='margin-left: 1rem;' title='Export this table as an Excel file.'></i>");
divInformation
.append("IRIS CODE: " + code_iris).append($("<br>"))
.append("IRIS: " + layer.feature.properties.NOM_IRIS).append($("<br>"))
.append("TOWNSHIP: " + layer.feature.properties.NOM_COM).append($("<br>"));
let moreInfosLink = $("<a>");
moreInfosLink
.prop("href", "details-iris.html?code_iris="+code_iris)
.prop("target", "_blank")
.text("More details")
.append($("<br>"));
divInformation.append(moreInfosLink).append(download);
}
if (selected_algorithm !== "undefined" && selected_algorithm !== undefined) {
predictions = predict(code_iris, selected_algorithm)
console.log(predictions)
}
let selectAlgorithm = $("<select>")
selectAlgorithm
.prop("id", "selectAlgorithmTooltip")
.append($("<option>").prop("value", "undefined").text("---"))
for(let algorithm of classifiers) {
selectAlgorithm.append($("<option>").prop("value", algorithm).text(algorithm));
}
previously_selected_algorithm = selected_algorithm;
let divPredictions = $("<div>").prop("id", "divPredictions");
let tablePredictions = $("<table>").prop("id", "tablePredictions");
tablePredictions.append("<th><td>Environment value</td><td>Prediction</td><td>Frequency</td></th>")
let row, colEnv, colValue, colFrequency;
if (predictions !== undefined) {
for (let key in predictions) {
divPredictions.append(
capitalizeFirstLetter(key.split("_").join(" ")) + ': '
+ predictions[key]["most_frequent"]
+ " (" + predictions[key]["count_frequent"] + "/7)"
).append($('<br>'));
row = $("<tr>");
colEnv = $("<td>").html(capitalizeFirstLetter(key.split("_").join(" ")));
colValue = $("<td>").html(predictions[key]["most_frequent"]);
colFrequency = $("<td>").html(predictions[key]["count_frequent"] + "/7");
row.append(colEnv, colValue, colFrequency)
tablePredictions.append(row);
}
console.log(tablePredictions);
download.on("click", function (e) {
e.preventDefault();
tablePredictions.table2excel({
type: 'xls',
filename: 'predictions'+code_iris+'.xls',
preserveColors: true
});
});
}
let messageTooltip = divInformation[0].outerHTML + selectAlgorithm[0].outerHTML + divPredictions[0].outerHTML;
console.log(messageTooltip)
layer.bindPopup(messageTooltip)
layer.bringToFront();
layer.openPopup();
$("#selectAlgorithmTooltip").val(previously_selected_algorithm); // must be after binding the popup to be effective
$("#selectAlgorithmTooltip").on("click", function() { displayPopup(e)}) // update popup (env variables) when click on an algorithm
}
/**
* Add IRIS layer from GeoJSON data
* @param {geojson} geojson .
* @param {event} events .
* @param {object} style .
* @param {string} typeMethod . (specify the method which caused this display, ex "searchBounds", "searchCode", "searchName")
* @param {function} callback .
*/
function addLayerFromGeoJSON(geojson, events, style, typeMethod){
if(irisLayer != null) { // if already displayed iris, remove them
removeLayer(irisLayer);
}
if(geojson != null) {
irisLayer = new L.geoJSON(geojson, {onEachFeature: events});
irisLayer.setStyle(style);
irisLayer.addTo(map);
if(typeMethod != "searchBounds") // if searchBounds (zoom), fitBounds() will decrease the zoom, thus reloading searchBounds...
map.fitBounds(irisLayer.getBounds()); // zoom on the displayed iris
}
return irisLayer;
}
/**
* Add tooltip, mouseover, mouseout and click events to the (features of) IRIS layer
* @param {number} feature .
* @param {layer} layer .
*/
function eventsIRIS(feature, layer) {
layer.on({
// mouseover: highlightFeature,
//mouseout: resetHighlight,
click: displayPopup //showPredictions
});
}
/**
* Allow the validation of input fields using "enter key".
* @param event the event gathered (enter key pressed)
*/
function eventValidateButton(event) {
// a generic method to allow the validation of input fields using "enter key"
if(event.keyCode == 13) // enter key has been pressed and released, back to parent and click on the <button>
event.target.parentNode.querySelector("button").click();
}
// updating values of printed parameters
$("#inputZoomLevel").val(DEFAULT_ZOOM_LEVEL_MIN_FOR_DISPLAY);
// linking elements (buttons, body) to events
$("#boutonRechercherCode").click(getIrisFromCode);
$("#inputCode").keyup(eventValidateButton);
$("#boutonRechercherNom").click(getIrisFromName);
$("#inputName").keyup(eventValidateButton);
$("#boutonEffacer").click(removeLayer);
$(document).ready(initialize); // when the page is loaded, initialize the map
$("#boutonEnableDisableZoom").click(function() {
if($("#inputZoomLevel").prop("disabled")) { // enable the zoom input
$("#boutonEnableDisableZoom > img").attr("src", "./static/css/open-iconic-master/svg/lock-unlocked.svg");
$("#inputZoomLevel").removeAttr("disabled"); // prop({disabled: false});
}
else { // disable the zoom input
$("#boutonEnableDisableZoom > img").attr("src", "./static/css/open-iconic-master/svg/lock-locked.svg");
$("#inputZoomLevel").prop("disabled", true);
}
})
/**
* Send an AJAX request to get predictions for the given IRIS.
* @param iris_code a string containing the code of the IRIS to predict.
* @param algorithm_name a strting containing the name of the algorithm used to predict environment.
* @returns {} a dictionary containing results of predictions, i.e. a value and a score for each EV.
*/
function predict(iris_code, algorithm_name) {
$("body").css("cursor", "progress");
let predictions = null;
$.ajax({
type: "GET",
url: "/predict_iris",
data: {
'iris_code': iris_code,
'algorithm_name': algorithm_name
},
"async": false,
contentType: 'application/json;charset=UTF-8',
success: function(result) {
console.log(result);
console.log(result['predictions']);
predictions = result['predictions'];
if(result['message'] === "KO") { alert("Your train_size or test_size parameter was set badly. The algorithm has been run with default parameters which are 80% for train_size and 20% for test_size."); }
$("body").css("cursor", "default");
},
error: function(result, textStatus, errorThrown) {
console.log(errorThrown);
alert("There is an issue to predict environment of this IRIS. You can check the console to have more details. " + result + textStatus + errorThrown);
$("body").css("cursor", "default");
}
});
return predictions
}
\ No newline at end of file
{% extends "base.html" %}
{% block content %}
<div class="row">
<aside id="sidebar" class="col-3 min-vh-100 max-vh-100" style="position: relative;">
{% include 'header.html' %}
{% if language == "french" %}
<p class="text-gray font-weight-bold text-uppercase px-3 small pb-4 mb-0" title="Choisir un algorithm parmi la liste ci-dessous.">Choisir un algorithme</p>
{% else %}
<p class="text-gray font-weight-bold text-uppercase px-3 small pb-4 mb-0" title="Choose an algorithm among the list below.">Select an algorithm</p>
{% endif %}
<form id="formAlgorithm" class="px-3 small">
<select id="selectAlgorithm">
{% if language == "french" %}
<option selected value="Algorithme"> -- choisir un algorithme --</option>
{% else %}
<option selected value="Algorithm"> -- select an algorithm --</option>
{% endif %}
</select>
</form>
<div id="tuningSection" style="visibility: hidden">
<hr/>
{% if language == "french" %}
<p class="font-weight-bold text-uppercase px-3 small" title="Paramétrer l'algorithme choisi.">Paramétrer l'algorithme</p>
{% else %}
<p class="font-weight-bold text-uppercase px-3 small" title="Tune the selected algorithm.">Tune algorithm</p>
{% endif %}
<form id="formParameters">
<div class="col-12" id="divParameters">
{% if language == "french" %}
<h6>Paramètres spécifiques<i id="specificParametersTitle" class="fas fa-angle-double-up"></i></h6>
<ul id="specificParameters" class="nav flex-column bg-white mb-0" style="display: block"></ul>
<h6>Paramètres communs<i id="commonParametersTitle" class="fas fa-angle-double-up"></i></h6>
<ul id="commonParameters" class="nav flex-column bg-white mb-0" style="display: block"></ul>
{% else %}
<h6>Specific parameters<i id="specificParametersTitle" class="fas fa-angle-double-up"></i></h6>
<ul id="specificParameters" class="nav flex-column bg-white mb-0" style="display: block"></ul>
<h6>Common parameters<i id="commonParametersTitle" class="fas fa-angle-double-up"></i></h6>
<ul id="commonParameters" class="nav flex-column bg-white mb-0" style="display: block"></ul>
{% endif %}
</div>
</form>
{% if language == "french" %}
<p class="font-weight-bold text-uppercase px-3 small" title="Paramétrer la répartition entre les jeux d'apprentissage et de test." style="padding-top: 1rem; padding-bottom: 0; margin-bottom: 0">Jeux de données</p>
{% else %}
<p class="font-weight-bold text-uppercase px-3 small" title="Tune the repartition of the data into train and test sets." style="padding-top: 1rem; padding-bottom: 0; margin-bottom: 0">Tune dataset</p>
{% endif %}
<ul class="nav flex-column bg-white mb-0">
<li class="nav-item">
<div class="nav-link">
{% if language == "french" %}
<i class="fa fa-question-circle mr-3 text-primary fa-fw" title="Taille des données d'entraînement. La valeur est un pourcentage entre 1 et 99%."></i>
Données d'entraînement
<input id="trainPercentage" type="number" min="1" max="99" step="1" value="80" title="Le pourcentage des données utilisées pour l'apprentissage.">
{% else %}
<i class="fa fa-question-circle mr-3 text-primary fa-fw" title="Size for the train set. The value is a percentage and should be between 1 and 99%."></i>
Train size
<input id="trainPercentage" type="number" min="1" max="99" step="1" value="80" title="The percentage of the dataset used to train the algorithm.">
{% endif %}
</div>
</li>
<li class="nav-item">
<div class="nav-link">
{% if language == "french" %}
<i class="fa fa-question-circle mr-3 text-primary fa-fw" title="Taille des données de test. La valeur est un pourentage entre 1 et 99%."></i>
Données de test
<input id="testPercentage" type="number" min="1" max="99" step="1" value="20" title="Le pourcentage des données utilisées pour le test.">
{% else %}
<i class="fa fa-question-circle mr-3 text-primary fa-fw" title="Size for the test set. The value is a percentage and should be between 1 and 99%."></i>
Test size
<input id="testPercentage" type="number" min="1" max="99" step="1" value="20" title="The percentage of the dataset used to test the algorithm.">
{% endif %}
</div>
</li>
<li class="nav-item">
<div class="nav-link">
{% if language == "french" %}
<i class="fa fa-question-circle mr-3 text-primary fa-fw" title="Cocher pour retirer les IRIS détectés comme abberants du jeu de données."></i>
Retirer les IRIS abberants
<input id="removeOutliers" type="checkbox" title="Cocher pour retirer les IRIS abbertants.">
<br>
<i class="fa fa-question-circle mr-3 text-primary fa-fw" title="Cocher pour retirer les IRIS ruraux du jeu de données."></i>
Retirer les IRIS ruraux
<input id="removeRural" type="checkbox" title="Cocher pour retirer els IRIS ruraux.">
{% else %}
<i class="fa fa-question-circle mr-3 text-primary fa-fw" title="Check it to remove outliers in the dataset."></i>
Remove outliers
<input id="removeOutliers" type="checkbox" title="Check it to remove outliers.">
<br>
<i class="fa fa-question-circle mr-3 text-primary fa-fw" title="Check it to remove rural neighbourhoods in the dataset."></i>
Remove rural
<input id="removeRural" type="checkbox" title="Check it to remove rural neighbourhoods.">
<br>
{% endif %}
</div>
</li>
</ul>
{% if language == "french" %}
<button id="runBtn" class="btn btn-success" title="Entraîner et tester l'algorithme paramétré sur les données.">
Entraîner, tester et évaluer
</button>
{% else %}
<button id="runBtn" class="btn btn-success" title="Train and test the tuned algorithm on data.">
Train, test and evaluate
</button>
{% endif %}
</div>
{% include 'footer.html' %}
</aside>
<main class="col-9" id="resultsDiv">
<!-- <button id="sidebarCollapse" type="button" class="btn btn-light bg-white rounded-pill shadow-sm px-4 mb-4"><i class="fa fa-bars mr-2"></i><small class="text-uppercase font-weight-bold"></small></button> -->
{% if language == "french" %}
<h2 title="Résultats de l'algorihtme paramétré">Resultats<i class="far fa-trash-alt" id="clearResults"
title="Supprimer tous les résultats"
style="color: red; font-size: 22px; padding-left: 0.5rem"></i>
{% else %}
<h2 title="Results of the tuned algorithm">Results<i class="far fa-trash-alt" id="clearResults"
title="Clear all results"
style="color: red; font-size: 22px; padding-left: 0.5rem"></i>
{% endif %}
</h2>
</main>
</div>
<script src="{{ url_for('static', filename='js/algorithms.js') }}"></script>
<script src="{{ url_for('static', filename='js/utils.js') }}"></script>
{% endblock %}
<div style="text-align: justify;">
{% if language == "french" %}
<label for="inputZoomLevel">Niveau de zoom minimal pour afficher les IRIS automatiquement</label>
{% else %}
<label for="inputZoomLevel">Minimal zoom level to display IRIS automatically</label>
{% endif %}
<div class="input-group mb-4">
<div class="input-group-prepend">
<button class="btn" type="button" id="boutonEnableDisableZoom">
{% if language == "french" %}
<img src="{{url_for('static', filename='css/open-iconic-master/svg/lock-locked.svg')}}" width="16" height="16" alt="Activer/Désactiver" />
{% else %}
<img src="{{url_for('static', filename='css/open-iconic-master/svg/lock-locked.svg')}}" width="16" height="16" alt="Enable/Disable" />
{% endif %}
</button>
<input type="number" min="12" max="18" value="16" disabled maxlength="1" id="inputZoomLevel" style="width: 3em;" />
<span valign="bottom" class="ml-2 pt-1">
{% if language == "french" %}
(niveau de zoom actuel =&nbsp;<span id="spanZoomLevel" style="font-weight: bold;">6</span>)
{% else %}
(actual zoom level =&nbsp;<span id="spanZoomLevel" style="font-weight: bold;">6</span>)
{% endif %}
</span>
</div>
</div>
{% if language == "french" %}
<label for="boutonRechercherCode">Rechercher par code IRIS</label>
{% else %}
<label for="boutonRechercherCode">Search by IRIS code</label>
{% endif %}
<div class="input-group mb-4">
<input type="text" class="form-control" placeholder="740560104" aria-label="740560104" id="inputCode"/>
<div class="input-group-append">
<button class="btn" type="button" id="boutonRechercherCode">
<img src="{{url_for('static', filename='css/package/build/svg/search.svg')}}" alt="Search" />
</button>
</div>
</div>
{% if language == "french" %}
<label for="boutonRechercherNom">Rechercher par nom ou par ville</label><br>
{% else %}
<label for="boutonRechercherNom">Search by IRIS name or city</label><br>
{% endif %}
<div class="input-group mb-4">
<input type="text" class="form-control" placeholder="Lyon" pattern=".{3,}" aria-label="Lyon" id="inputName"/>
<div class="input-group-append">
<button class="btn" type="button" id="boutonRechercherNom">
<img src="{{url_for('static', filename='css/package/build/svg/search.svg')}}" alt="Search" />
</button>
</div>
<br>
</div>
<div class="input-group mb-3">
<button class="btn" type="button" id="boutonEffacer">
{% if language == "french" %}
Effacer
<img class="align-middle" src="{{url_for('static', filename='css/package/build/svg/trashcan.svg')}}" alt="Effacer" />
{% else %}
Clear
<img class="align-middle" src="{{url_for('static', filename='css/package/build/svg/trashcan.svg')}}" alt="Clear" />
{% endif %}
</button>
</div>
</div>
\ No newline at end of file
#!/usr/bin/env python
# encoding: utf-8
# =============================================================================
# Unit tests for predihood.
# =============================================================================
import os
import pandas as pd
import unittest
from predihood.config import FOLDER_DATASETS, ENVIRONMENT_VALUES
from predihood.utility_functions import check_train_test_percentages, intersection, union, similarity, \
get_most_frequent, address_to_code, address_to_city, indicator_full_to_short_label, \
indicator_short_to_full_label, get_classifier, set_classifier, signature_of_algorithm, add_assessment_to_file
from sklearn.neighbors import KNeighborsClassifier
class TestCase(unittest.TestCase):
"""
A class for Predihood unit tests.
"""
def test_address_to_code(self):
# test if converting an address into a code gives the correct code
address = "46 avenue Victor Hugo Tassin"
code = address_to_code(address)
assert code == "692440201"
assert 1 != "1"
# test if converting an address not located in France returns None
address = "Westminster, London SW1A 0AA, United Kingdom"
code = address_to_code(address)
assert code is None
def test_address_to_city(self):
# test if converting an address into a city gives the correct city
address = "46 avenue Victor Hugo Tassin"
city = address_to_city(address)
assert city == "Tassin-la-Demi-Lune"
def test_indicator_full_to_short_label(self):
# test if converting a full label of an indicator into its short label gives the correct short label
full_label = "Pop 11-17 ans en 2014 (princ)"
short_label = indicator_full_to_short_label(full_label)
assert short_label == "P14_POP1117"
def test_indicator_short_to_full_label(self):
# test if converting a short label of an indicator into its full label gives the correct full label
short_label = "P14_POP1117"
full_label = indicator_short_to_full_label(short_label)
assert full_label == "Pop 11-17 ans en 2014 (princ)"
def test_get_classifier(self):
# test if selecting a classifier gives the correct object
classifier_name = "KNeighbors Classifier"
classifier = get_classifier(classifier_name)
# classifier == KNeighborsClassifier() fails because they are different objects
assert classifier.isistance(type(KNeighborsClassifier()))
def test_set_classifier(self):
# test if setting the parameters of a classifier changes its internal parameters
classifier_name = "KNeighbors Classifier"
classifier = get_classifier(classifier_name)
assert classifier.n_neighbors == 5 # default is 5
parameters = {"n_neighbors": 10}
classifier = set_classifier(classifier, parameters)
assert classifier.n_neighbors == 10
def test_signature(self):
# test if the signature function is able to pick correct parameters
classifier_name = "KNeighbors Classifier"
classifier_signature = signature_of_algorithm(classifier_name)
assert "n_neighbors" in classifier_signature
assert classifier_signature["n_neighbors"]["types"] == ["int"]
assert classifier_signature["n_neighbors"]["default"] == "5"
def test_train_test_percentages(self):
# test if train and test sizes are correctly changed if needed
train_size, test_size = check_train_test_percentages(0.7, 0.3)
assert train_size == 0.7
assert test_size == 0.3
train_size, test_size = check_train_test_percentages(40, 60)
assert 0 < train_size < 1
assert 0 < test_size < 1
assert train_size + test_size == 1
train_size, test_size = check_train_test_percentages(0.7, 0.4)
assert 0 < train_size < 1
assert 0 < test_size < 1
assert train_size + test_size == 1
def test_intersection(self):
# test if intersection gives the correct output
l1 = [1, 2, 3]
l2 = [2, 3, 4]
result = intersection(l1, l2)
assert result == [2, 3]
def test_union(self):
# test if union gives the correct output
l1 = [1, 2, 3]
l2 = [2, 3, 4]
result = union(l1, l2)
assert result == [1, 2, 3, 4]
def test_similarity(self):
# test if a given value is correctly compared to already added values by checking the returned index
value = "Countyside"
lst = [["Houses", "House"], ["Countryside", "Countrysid"], ["Green areas"]]
index = similarity(value, lst)
assert index == 1
value = "Countyside"
lst = [["Countrysidee", "Coutysid"]]
index = similarity(value, lst)
assert index == -1
value = "Countryside"
lst = [["Countryside", "Countrysid"]]
index = similarity(value, lst)
assert index == -2
def test_get_most_frequent(self):
# test if the most frequent function gives the correct value and count correctly the number of occurrences
lst = ["Houses", "Houses", "Towers", "Housing estate", "Houses"]
result = get_most_frequent(lst)
assert result["most_frequent"] == "Houses"
assert result["count_frequent"] == 3
def test_add_assessment_to_file(self):
# test if an IRIS is correctly added to the dataset and if it is not appended twice
code_iris = "692440201"
values = ["Houses", "Housing", "Green areas", "Peri-urban", "West", "Upper middle"]
add_assessment_to_file(code_iris, values)
code_iris = "692440201"
values = ["Houses", "Housing", "Green areas", "Peri-urban", "West", "Upper middle"]
result = add_assessment_to_file(code_iris, values)
assert result == "iris already assessed"
def test_values_dataset(self):
# test if values used in dataset are the same than the one declared by social science researchers
filename = os.path.join(FOLDER_DATASETS, "data_density.csv")
dataset = pd.read_csv(filename)
values_for_building_type = set([value for key, value in ENVIRONMENT_VALUES["building_type"].items()])
assert set(dataset["building_type"].tolist()) == values_for_building_type
if __name__ == "__main__":
unittest.main(verbosity=2) # run all tests with verbose mode
import ast
import inspect
import json
import logging
import sys
import numpy as np
import pandas as pd
import re
import requests
import stringdist
from area import area
from inspect import signature
from predihood import model
from predihood.classifiers_list import AVAILABLE_CLASSIFIERS
from predihood.config import TRAIN_SIZE, TEST_SIZE, ENVIRONMENT_VARIABLES, TRANSLATION, OLD_PREFIX, NEW_PREFIX, FILE_MANUAL_ASSESSMENT
log = logging.getLogger(__name__)
# 1. IRIS function
def address_to_code(address):
"""
Get IRIS code from address.
Args:
address: a string containing the address of the iris
Returns:
a string containing the code of the searched address
"""
response = requests.get("https://pyris.datajazz.io/api/search/", params=[("q", address)])
json_response = response.json()
return str(json_response["complete_code"]) if "complete_code" in json_response else None
def address_to_city(address):
"""
Get city from address.
Args:
address: a string containing the address of the iris
Returns:
a string containing the city of the searched address
"""
response = requests.get("https://pyris.datajazz.io/api/search/", params=[("q", address)])
json_response = response.json()
return str(json_response["city"]) if "city" in json_response else None
def append_indicator(raw_indicator, iris, lst, append_col, indicators):
"""
Append the value of an INSEE indicator to a list corresponding to the data of the assessed IRIS (departure or arrival).
Args:
raw_indicator: a string containing the name of the indicator, e.g. P14_POP
iris: the iris object that contains the indicator
lst: the list where to append the indicator's value
append_col: True to append the indicator to the cols variable
indicators: the list of the columns of the dataset, i.e. the indicators
Returns:
the list containing indicator' values and the other one containing indicators names.
"""
if iris is None: raise Exception("IRIS have no attributes")
if raw_indicator in iris["properties"]["raw_indicators"]:
val_indicator = iris["properties"]["raw_indicators"][raw_indicator]
# append NaN if indicator is null, else append the value
lst.append(np.nan) if (val_indicator is None or not val_indicator) else lst.append(val_indicator)
else:
lst.append(np.nan)
if append_col: indicators.append(raw_indicator)
return lst, indicators
def append_target(row, target, lst):
"""
Append the target to the current list (departure or arrival).
Args:
row: a list corresponding to the current row of dataset
target: a string containing the target to append, i.e. the value of the EV
lst: the list where the target is append
Returns:
the list with the appended target
"""
if target == OLD_PREFIX + "geographical_position" or target == NEW_PREFIX + "geographical_position":
# get only geo position without the city, e.g. South-East Lyon gives South-East
if str(row[target]) == "nan":
city = np.nan
else:
city = row[target].split(" ")[0]
# city_name = ''.join(split_city[1:len(split_city)])
value = TRANSLATION[city] if city in TRANSLATION else np.nan
lst.append(value)
else:
value = TRANSLATION[row[target]] if row[target] in TRANSLATION else np.nan
lst.append(value)
return lst
def indicator_full_to_short_label(full_label):
"""
Convert the full label of an indicator to its short label.
Args:
full_label: a string containing the full label of the indicator, e.g. Population 0-2 y.o. in 2014
Returns:
the short label of the given indicator, e.g. P14_POP0002
"""
indicators = model.get_indicators_dict()
key_list = list(indicators.keys())
val_list = list(indicators.values())
if full_label not in indicators.values():
return key_list[val_list.index(full_label + " ")]
else:
return key_list[val_list.index(full_label)]
def indicator_short_to_full_label(short_label):
"""
Convert the short label of an indicator to its full label.
Args:
short_label: a string containing the short label of the indicator, e.g. P14_POP0002
Returns:
the full label of the indicator, e.g. Population 0-2 y.o. in 2014
"""
indicators = model.get_indicators_dict()
return indicators[short_label]
def apply_hierarchy(selected_indicators, hierarchy):
"""
Apply hierarchy on the given indicators in order to go up children indicators in their parents.
Args:
selected_indicators: a list of indicators selected by the feature importance process.
hierarchy: the hierarchy of the indicators, i.e. for each indicator, there are its level in the hierarchy and its first ancestor.
Returns:
the new selected indicators list, with some children which have go up in their parents.
"""
list_indicators_FI = [selected_indicators[j][0] for j in range(len(selected_indicators))]
indexes_to_remove = []
for i in range(len(selected_indicators)):
index_row = hierarchy.index[hierarchy["INDICATOR"] == selected_indicators[i][0]].tolist()
if len(index_row) == 0:
continue # pass this indicator because it does not exist in the hierarchy
else:
index_row = index_row[0]
level = hierarchy.iloc[index_row, 2]
ancestor = hierarchy.iloc[index_row, 3]
if level > 1:
if ancestor in list_indicators_FI:
index_ancestor = list_indicators_FI.index(ancestor) if ancestor in list_indicators_FI else None
while index_ancestor in indexes_to_remove:
ancestor2 = hierarchy.iloc[hierarchy.index[hierarchy["INDICATOR"] == ancestor].tolist()[0], 3] # name of ancestor
ancestor = ancestor2
index_ancestor = list_indicators_FI.index(ancestor) if ancestor in list_indicators_FI else None
if hierarchy.iloc[hierarchy.index[hierarchy["INDICATOR"] == ancestor].tolist()[0], 2] == 1:
break
if index_ancestor not in indexes_to_remove:
selected_indicators[index_ancestor][1] += selected_indicators[i][1]
indexes_to_remove.append(i)
for index in sorted(indexes_to_remove,reverse=True): # remove in reverse order to do not throw off subsequent indexes
del selected_indicators[index]
return selected_indicators
def get_classifier(name):
"""
Get an instance of a classifier with its name.
Args:
name: a string containing the name of the desired classifier
Returns:
an instance of a classifier
"""
classifier_object = AVAILABLE_CLASSIFIERS[name]
return classifier_object()
def set_classifier(classifier, parameters):
"""
Tune the classifier with the given parameters.
Args:
classifier: an instance of the classifier to tune
parameters: a dictionary containing the tuning parameters
Returns:
an instance of the tuned classifier
"""
keys_clf = list(classifier.get_params().keys())
# remove None parameters and parameters that don't exist in sklearn (e.g. train and test size)
parameters = {key: value for key, value in parameters.items() if value != "" and key in keys_clf}
classifier.set_params(**parameters)
return classifier
def signature_of_algorithm(chosen_algorithm):
"""
Get the signature of an algorithm, i.e. its parameters, the default values and the type of each parameter. The documentation of the algorithm must be in NumPy style.
Args:
chosen_algorithm: a string containing the name of the algorithm, e.g. RandomForestClassifier
Returns:
the signature of the given algorithm, i.e. a dictionary containing for each parameter:
- a list of the accepted types
- the default value
- a description of the parameter (e.g. "The train_size parameter aims at tuning the size of the sample during the learning step.")
"""
if chosen_algorithm == "Algorithm": return json.dumps({}), "no_selection" # special case for no selection
# getting parameters and default values
parameters = {}
model = get_classifier(chosen_algorithm)
if sys.version_info.major < 3 or (sys.version_info.major == 3 and sys.version_info.minor < 8):
params = inspect.getfullargspec(model.__init__).args[1:] # get parameter' names -- [1:] to remove self parameter
defaults = inspect.getfullargspec(model.__init__).defaults # get default values
else:
# getfullargspec is deprecated since Python 3.8, need to use inspect?signature instead
sig = inspect.signature(model.__init__)
params, defaults = [], []
for param in sig.parameters.values():
params.append(param.name)
defaults.append(param.default)
if params is None or defaults is None: return json.dumps({}), "no_parameters"
assert len(params) == len(defaults)
# getting the definition of parameters
try:
doc = model.__doc__
param_section = "Parameters"
dashes = "-" * len(param_section) # -------
number_spaces = doc.find(dashes) - (doc.find(param_section) + len(param_section))
attribute_section = "Attributes\n"
# sub_doc is the param section of the docs (i.e. without attributes and some text)
sub_doc = doc[doc.find(param_section) + len(param_section) + number_spaces + len(dashes) + len("\n"):doc.find(attribute_section)]
except:
return json.dumps({}), "no_documentation"
for i in range(len(params)):
param_name = str(params[i]) + " : "
index_param = sub_doc.find(param_name)
index_next_newline = sub_doc[index_param:].find("\n") # find returns the first occurrence
parameter_string = sub_doc[index_param:index_param + index_next_newline]
doc_param = sub_doc[index_param + index_next_newline:]
index_end_sentence = re.search("(\.\s)", doc_param).start() # search for the first sentence
first_sentence = doc_param[:index_end_sentence + 1]
# format first sentence to have a prettier display.
first_sentence = first_sentence.replace("\n", " ")
while " " in first_sentence:
first_sentence = first_sentence.replace(" ", " ")
types_and_default = parameter_string[len(param_name):]
if "{" in types_and_default and "}" in types_and_default: # for cases like {"auto", "kd_tree", "brute"}, optional
types_and_default = types_and_default.replace("{", '')
types_and_default = types_and_default.replace("}", '')
if " or " in types_and_default: types_and_default = types_and_default.replace(" or ", ", ")
types_defaults_split = types_and_default.split(", ")
types = []
default = -1
variants = ["optional (default=", "optional (default = ", "optional", "(default=", "(default = ", "default ",
"default: ", "default="] # DO NOT CHANGE THE ORDER OF ITEMS
for item in types_defaults_split:
if not any(value in item for value in variants):
if item.startswith("length"):
pass # exceptions
else:
types.append(item) # item is a type
else:
for value in variants:
if value in item:
if value.startswith("optional ("):
default = item.split(value)[1][:-1]
elif value.startswith("(default"):
default = item.split(value)[1][:-1]
elif value.startswith("default"):
default = item.split(value)[1]
elif value == "optional":
default = "None"
break # do not iterate over other values
if default != -1 and default != "None":
type_of_default = str(type(ast.literal_eval(str(default))).__name__)
else:
type_of_default = "str"
types[:] = ["int" if x == "integer" else x for x in types] # replace "integer" by "int"
types[:] = ["bool" if x == "boolean" else x for x in types] # replace "boolean" by "bool"
types[:] = ["str" if x == "string" else x for x in types] # replace "str" by "string"
if len(types) == 0: types.append(type_of_default) # fill missing types
types[:] = [x for x in types if "None" not in x and "NoneType" not in x] # remove None type
parameters[param_name[:-3]] = {"types": types, "default": default, "description": first_sentence} # -3 to remove " : "
return parameters, "OK"
def check_train_test_percentages(train_size, test_size):
"""
Check train and test size and update with defaults or divided by 100 if needed.
Args:
train_size: an integer or a float corresponding to the value for train size (should be between 0 and 1)
test_size: an integer or a float corresponding to the value for test size (should be between 0 and 1)
Returns:
the train and test sizes
"""
if 0 < train_size < 1 and 0 < test_size < 1 and train_size + test_size == 1:
message = "OK" # default case - everything is correct
elif 0 < train_size < 1 and 0 < test_size < 1:
message = "KO" # train_size or test_size is not correct so we set default parameters
train_size = TRAIN_SIZE # 0.8
test_size = TEST_SIZE # 0.2
if 1 <= train_size < 100 and 1 <= test_size < 100 and train_size + test_size == 100:
message = "OK" # default case - everything is correct
train_size = train_size/100
test_size = test_size/100
elif 1 <= train_size < 100 and 1 <= test_size < 100:
message = "KO" # train_size or test_size is not correct so we set default parameters
train_size = TRAIN_SIZE # 0.8
test_size = TEST_SIZE # 0.2
return train_size, test_size, message
# 2. list functions
def intersection(lst1, lst2):
"""
Intersect two lists.
Args:
lst1: a list corresponding to the first list to be intersected
lst2: a list corresponding to the second list to be intersected
Returns:
a list corresponding to the result of the intersection of the two given lists.
"""
return list(set(lst1) & set(lst2))
def union(lst1, lst2):
"""
Unify two lists without repetitions.
Args:
lst1: a list corresponding to the first list to append
lst2: a list corresponding to the second list to append
Returns:
a list corresponding to the union of the two lists
"""
return list(set(lst1) | set(lst2))
def similarity(value, lst):
"""
Check if a value is enough similar to the data.
Args:
value: the value on which the similarity is computed
lst: the list containing other values to check similarity
Returns:
the index of the similar value, -1 if no value is enough similar, -2 if the value is already added
"""
for i in range(len(lst)):
if value in lst[i]: return -2 # this value is already append
for elem in lst[i]:
if not isinstance(elem, float):
dissimilarity = stringdist.levenshtein(str(elem), str(value)) # compute Levenshtein similarity
if dissimilarity == 1: return i # if the given value has only one difference with the current value, store it as a similarity
return -1
def get_most_frequent(lst):
"""
Get the most frequent item in a list. If many elements are frequent, it returns the first one.
Args:
lst: the list to find the most frequent element
Returns:
a dictionary containing the most frequent of the given list and its count
"""
most_frequent_element = max(set(lst), key=lst.count)
dictionary = {"most_frequent": most_frequent_element, "count_frequent": lst.count(most_frequent_element)}
return dictionary
# 3. plot functions
def auto_label(rectangles, axes):
"""
Adds a text label above each bar in rectangles, displaying its value.
Args:
rectangles: the bars of the plot.
axes: the axes of the plot.
"""
for rect in rectangles:
height = rect.get_height()
axes.annotate("{}".format(height), xy=(rect.get_x() + rect.get_width() / 2, height), xytext=(0, 3), textcoords="offset points", ha="center", va="bottom")
def add_assessment_to_file(code_iris, values):
"""
Add an assessed IRIS to the CSV file.
Args:
code_iris: a string corresponding to the code of the IRIS (9 digits)
values: a list of values for the 6 EV that represent the environment of the assessed IRIS
Returns:
the string "okay" if the assessed IRIS has been added to the CSV file
"""
df = pd.read_csv(FILE_MANUAL_ASSESSMENT)
codes = df["CODE"].tolist()
codes_lst = [str(elem) for elem in codes]
if code_iris in codes_lst:
return "iris already assessed"
else:
iris_data = model.get_iris_from_code(code_iris)
iris_coords = model.get_coords_from_code(code_iris)
area_iris = area(iris_coords) / 1000000 if iris_coords is not None else None
density_iris = iris_data["properties"]["raw_indicators"]["P14_POP"] / area_iris if area_iris is not None and area_iris > 0 else None
iris = []
cols = ["CODE", "AREA", "DENSITY"]
# adding code, area and density
iris.append(code_iris)
iris.append(area_iris)
iris.append(density_iris)
# adding insee indicators
indicators = model.get_indicators_list()
indicators_to_remove = ["IRIS", "REG", "DEP", "UU2010", "COM", "LIBCOM", "TRIRIS", "GRD_QUART", "LIBIRIS", "TYP_IRIS", "MODIF_IRIS", "LAB_IRIS", "LIB_IRIS", "LIB_COM", "CODGEO", "LIBGEO"]
for indicator in indicators_to_remove:
if indicator in indicators:
indicators.remove(indicator)
for raw_indicator in indicators:
iris, cols = append_indicator(raw_indicator, iris_data, iris, True, cols)
iris.extend(values) # adding assessed values
cols.extend(ENVIRONMENT_VARIABLES)
df = pd.DataFrame([iris])
df.to_csv(FILE_MANUAL_ASSESSMENT, mode="a", index=False, header=False) # DO NOT ERASE HEADER IN THE CSV FILE
return "okay"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment