diff --git a/.gitignore b/.gitignore
index b42097e86..02624a297 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
-**/__pycache__/
\ No newline at end of file
+.*
+__pycache__
+!.gitignore
diff --git a/NiBAx/NiBAxCmdApp.py b/NiBAx/NiBAxCmdApp.py
index ad8d124c6..e2d9ffb6d 100644
--- a/NiBAx/NiBAxCmdApp.py
+++ b/NiBAx/NiBAxCmdApp.py
@@ -8,7 +8,7 @@
from PyQt5 import QtCore, QtGui, QtWidgets
import os
import pandas as pd
-from NiBAx.plugins.loadsave.dataio import DataIO
+from NiBAx.core.dataio import DataIO
from NiBAx.plugins.sparesplugin.spares import SPARE, BrainAgeWorker
from NiBAx.core.model.datamodel import DataModel
diff --git a/NiBAx/core/MUSE_DerivedROIs_Mappings.csv b/NiBAx/core/MUSE_DerivedROIs_Mappings.csv
new file mode 100755
index 000000000..42c2d6eb0
--- /dev/null
+++ b/NiBAx/core/MUSE_DerivedROIs_Mappings.csv
@@ -0,0 +1,259 @@
+702,ICV
+701,TOTALBRAIN,4,11,23,30,31,32,35,36,37,38,39,40,41,47,48,49,50,51,52,55,56,57,58,59,60,61,62,71,72,73,75,76,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,100,101,102,103,104,105,106,107,108,109,112,113,114,115,116,117,118,119,120,121,122,123,124,125,128,129,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207
+601,GM,23,30,31,32,36,37,38,39,47,48,55,56,57,58,59,60,71,72,73,75,76,100,101,102,103,104,105,106,107,108,109,112,113,114,115,116,117,118,119,120,121,122,123,124,125,128,129,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207
+604,WM,40,41,61,62,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95
+606,GM_L,30,32,37,39,48,56,58,60,75,101,103,105,107,109,113,115,117,119,121,123,125,129,133,135,137,139,141,143,145,147,149,151,153,155,157,161,163,165,167,169,171,173,175,177,179,181,183,185,187,191,193,195,197,199,201,203,205,207
+607,WM_L,41,62,82,84,86,88,90,92,94
+613,GM_R,23,31,36,38,47,55,57,59,76,100,102,104,106,108,112,114,116,118,120,122,124,128,132,134,136,138,140,142,144,146,148,150,152,154,156,160,162,164,166,168,170,172,174,176,178,180,182,184,186,190,192,194,196,198,200,202,204,206
+614,WM_R,40,61,81,83,85,87,89,91,93
+501,CORPUS_CALLOSUM,95
+502,CEREBELLUM,38,39,40,41,71,72,73
+503,DEEP_WM_GM,23,30,31,32,36,37,47,48,55,56,57,58,59,60,75,76,89,90,91,92,93,94
+504,FRONTAL,81,82,102,103,104,105,112,113,118,119,120,121,124,125,136,137,140,141,142,143,146,147,150,151,152,153,162,163,164,165,172,173,174,175,178,179,182,183,186,187,190,191,192,193,204,205
+505,LIMBIC,100,101,116,117,138,139,166,167,170,171
+506,OCCIPITAL,83,84,108,109,114,115,128,129,134,135,144,145,156,157,160,161,196,197
+507,PARIETAL,85,86,106,107,148,149,168,169,176,177,194,195,198,199
+508,TEMPORAL,87,88,122,123,132,133,154,155,180,181,184,185,200,201,202,203,206,207
+509,VENTRICLE,4,11,49,50,51,52
+510,CEREBELLUM_L,39,41
+511,DEEP_WM_GM_L,30,32,37,48,56,58,60,75,90,92,94
+512,FRONTAL_L,82,103,105,113,119,121,125,137,141,143,147,151,153,163,165,173,175,179,183,187,191,193,205
+513,LIMBIC_L,101,117,139,167,171
+514,OCCIPITAL_L,84,109,115,129,135,145,157,161,197
+515,PARIETAL_L,86,107,149,169,177,195,199
+516,TEMPORAL_L,88,123,133,155,181,185,201,203,207
+517,VENTRICLE_L,50,52
+518,CEREBELLUM_R,38,40
+519,DEEP_WM_GM_R,23,31,36,47,55,57,59,76,89,91,93
+520,FRONTAL_R,81,102,104,112,118,120,124,136,140,142,146,150,152,162,164,172,174,178,182,186,190,192,204
+521,LIMBIC_R,100,116,138,166,170
+522,OCCIPITAL_R,83,108,114,128,134,144,156,160,196
+523,PARIETAL_R,85,106,148,168,176,194,198
+524,TEMPORAL_R,87,122,132,154,180,184,200,202,206
+525,VENTRICLE_R,49,51
+401,BASAL_GANGLIA,23,30,36,37,55,56,57,58
+402,DEEP_GM,59,60
+403,DEEP_WM,89,90,91,92,93,94
+404,FRONTAL_GM,102,103,104,105,112,113,118,119,120,121,124,125,136,137,140,141,142,143,146,147,150,151,152,153,162,163,164,165,172,173,174,175,178,179,182,183,186,187,190,191,192,193,204,205
+405,FRONTAL_WM,81,82
+406,LIMBIC_GM,100,101,116,117,138,139,166,167,170,171
+407,OCCIPITAL_GM,108,109,114,115,128,129,134,135,144,145,156,157,160,161,196,197
+408,OCCIPITAL_WM,83,84
+409,PARIETAL_GM,106,107,148,149,168,169,176,177,194,195,198,199
+410,PARIETAL_WM,85,86
+411,TEMPORAL_GM,122,123,132,133,154,155,180,181,184,185,200,201,202,203,206,207
+412,TEMPORAL_WM,87,88
+413,BASAL_GANGLIA_L,30,37,56,58
+414,DEEP_GM_L,60
+415,DEEP_WM_L,90,92,94
+416,FRONTAL_GM_L,103,105,113,119,121,125,137,141,143,147,151,153,163,165,173,175,179,183,187,191,193,205
+417,FRONTAL_WM_L,82
+418,LIMBIC_GM_L,101,117,139,167,171
+419,OCCIPITAL_GM_L,109,115,129,135,145,157,161,197
+420,OCCIPITAL_WM_L,84
+421,PARIETAL_GM_L,107,149,169,177,195,199
+422,PARIETAL_WM_L,86
+423,TEMPORAL_GM_L,123,133,155,181,185,201,203,207
+424,TEMPORAL_WM_L,88
+425,BASAL_GANGLIA_R,23,36,55,57
+426,DEEP_GM_R,59
+427,DEEP_WM_R,89,91,93
+428,FRONTAL_GM_R,102,104,112,118,120,124,136,140,142,146,150,152,162,164,172,174,178,182,186,190,192,204
+429,FRONTAL_WM_R,81
+430,LIMBIC_GM_R,100,116,138,166,170
+431,OCCIPITAL_GM_R,108,114,128,134,144,156,160,196
+432,OCCIPITAL_WM_R,83
+433,PARIETAL_GM_R,106,148,168,176,194,198
+434,PARIETAL_WM_R,85
+435,TEMPORAL_GM_R,122,132,154,180,184,200,202,206
+436,TEMPORAL_WM_R,87
+301,FRONTAL_INFERIOR_GM,104,105,136,137,146,147,178,179
+302,FRONTAL_INSULAR_GM,102,103,172,173
+303,FRONTAL_LATERAL_GM,120,121,142,143,162,163,164,165,182,183,190,191,204,205
+304,FRONTAL_MEDIAL_GM,124,125,140,141,150,151,152,153,186,187,192,193
+305,FRONTAL_OPERCULAR_GM,112,113,118,119,174,175
+306,LIMBIC_CINGULATE_GM,100,101,138,139,166,167
+307,LIMBIC_MEDIALTEMPORAL_GM,116,117,170,171
+308,OCCIPITAL_INFERIOR_GM,160,161
+309,OCCIPITAL_LATERAL_GM,128,129,144,145,156,157,196,197
+310,OCCIPITAL_MEDIAL_GM,108,109,114,115,134,135
+311,PARIETAL_LATERAL_GM,106,107,176,177,194,195,198,199
+312,PARIETAL_MEDIAL_GM,148,149,168,169
+313,TEMPORAL_INFERIOR_GM,122,123
+314,TEMPORAL_LATERAL_GM,132,133,154,155,200,201,202,203
+315,TEMPORAL_SUPRATEMPORAL_GM,180,181,184,185,206,207
+316,FRONTAL_INFERIOR_GM_L,105,137,147,179
+317,FRONTAL_INSULAR_GM_L,103,173
+318,FRONTAL_LATERAL_GM_L,121,143,163,165,183,191,205
+319,FRONTAL_MEDIAL_GM_L,125,141,151,153,187,193
+320,FRONTAL_OPERCULAR_GM_L,113,119,175
+321,LIMBIC_CINGULATE_GM_L,101,139,167
+322,LIMBIC_MEDIALTEMPORAL_GM_L,117,171
+323,OCCIPITAL_INFERIOR_GM_L,161
+324,OCCIPITAL_LATERAL_GM_L,129,145,157,197
+325,OCCIPITAL_MEDIAL_GM_L,109,115,135
+326,PARIETAL_LATERAL_GM_L,107,177,195,199
+327,PARIETAL_MEDIAL_GM_L,149,169
+328,TEMPORAL_INFERIOR_GM_L,123
+329,TEMPORAL_LATERAL_GM_L,133,155,201,203
+330,TEMPORAL_SUPRATEMPORAL_GM_L,181,185,207
+331,FRONTAL_INFERIOR_GM_R,104,136,146,178
+332,FRONTAL_INSULAR_GM_R,102,172
+333,FRONTAL_LATERAL_GM_R,120,142,162,164,182,190,204
+334,FRONTAL_MEDIAL_GM_R,124,140,150,152,186,192
+335,FRONTAL_OPERCULAR_GM_R,112,118,174
+336,LIMBIC_CINGULATE_GM_R,100,138,166
+337,LIMBIC_MEDIALTEMPORAL_GM_R,116,170
+338,OCCIPITAL_INFERIOR_GM_R,160
+339,OCCIPITAL_LATERAL_GM_R,128,144,156,196
+340,OCCIPITAL_MEDIAL_GM_R,108,114,134
+341,PARIETAL_LATERAL_GM_R,106,176,194,198
+342,PARIETAL_MEDIAL_GM_R,148,168
+343,TEMPORAL_INFERIOR_GM_R,122
+344,TEMPORAL_LATERAL_GM_R,132,154,200,202
+345,TEMPORAL_SUPRATEMPORAL_GM_R,180,184,206
+4,3rd Ventricle,4
+11,4th Ventricle,11
+23,Right Accumbens Area,23
+30,Left Accumbens Area,30
+31,Right Amygdala,31
+32,Left Amygdala,32
+35,Brain Stem,35
+36,Right Caudate,36
+37,Left Caudate,37
+38,Right Cerebellum Exterior,38
+39,Left Cerebellum Exterior,39
+40,Right Cerebellum White Matter,40
+41,Left Cerebellum White Matter,41
+47,Right Hippocampus,47
+48,Left Hippocampus,48
+49,Right Inf Lat Vent,49
+50,Left Inf Lat Vent,50
+51,Right Lateral Ventricle,51
+52,Left Lateral Ventricle,52
+55,Right Pallidum,55
+56,Left Pallidum,56
+57,Right Putamen,57
+58,Left Putamen,58
+59,Right Thalamus Proper,59
+60,Left Thalamus Proper,60
+61,Right Ventral DC,61
+62,Left Ventral DC,62
+71,Cerebellar Vermal Lobules I-V,71
+72,Cerebellar Vermal Lobules VI-VII,72
+73,Cerebellar Vermal Lobules VIII-X,73
+75,Left Basal Forebrain,75
+76,Right Basal Forebrain,76
+81,frontal lobe WM right,81
+82,frontal lobe WM left,82
+83,occipital lobe WM right,83
+84,occipital lobe WM left,84
+85,parietal lobe WM right,85
+86,parietal lobe WM left,86
+87,temporal lobe WM right,87
+88,temporal lobe WM left,88
+89,fornix right,89
+90,fornix left,90
+91,anterior limb of internal capsule right,91
+92,anterior limb of internal capsule left,92
+93,posterior limb of internal capsule inc. cerebral peduncle right,93
+94,posterior limb of internal capsule inc. cerebral peduncle left,94
+95,corpus callosum,95
+100,Right ACgG anterior cingulate gyrus,100
+101,Left ACgG anterior cingulate gyrus,101
+102,Right AIns anterior insula,102
+103,Left AIns anterior insula,103
+104,Right AOrG anterior orbital gyrus,104
+105,Left AOrG anterior orbital gyrus,105
+106,Right AnG angular gyrus,106
+107,Left AnG angular gyrus,107
+108,Right Calc calcarine cortex,108
+109,Left Calc calcarine cortex,109
+112,Right CO central operculum,112
+113,Left CO central operculum,113
+114,Right Cun cuneus,114
+115,Left Cun cuneus,115
+116,Right Ent entorhinal area,116
+117,Left Ent entorhinal area,117
+118,Right FO frontal operculum,118
+119,Left FO frontal operculum,119
+120,Right FRP frontal pole,120
+121,Left FRP frontal pole,121
+122,Right FuG fusiform gyrus,122
+123,Left FuG fusiform gyrus,123
+124,Right GRe gyrus rectus,124
+125,Left GRe gyrus rectus,125
+128,Right IOG inferior occipital gyrus,128
+129,Left IOG inferior occipital gyrus,129
+132,Right ITG inferior temporal gyrus,132
+133,Left ITG inferior temporal gyrus,133
+134,Right LiG lingual gyrus,134
+135,Left LiG lingual gyrus,135
+136,Right LOrG lateral orbital gyrus,136
+137,Left LOrG lateral orbital gyrus,137
+138,Right MCgG middle cingulate gyrus,138
+139,Left MCgG middle cingulate gyrus,139
+140,Right MFC medial frontal cortex,140
+141,Left MFC medial frontal cortex,141
+142,Right MFG middle frontal gyrus,142
+143,Left MFG middle frontal gyrus,143
+144,Right MOG middle occipital gyrus,144
+145,Left MOG middle occipital gyrus,145
+146,Right MOrG medial orbital gyrus,146
+147,Left MOrG medial orbital gyrus,147
+148,Right MPoG postcentral gyrus medial segment,148
+149,Left MPoG postcentral gyrus medial segment,149
+150,Right MPrG precentral gyrus medial segment,150
+151,Left MPrG precentral gyrus medial segment,151
+152,Right MSFG superior frontal gyrus medial segment,152
+153,Left MSFG superior frontal gyrus medial segment,153
+154,Right MTG middle temporal gyrus,154
+155,Left MTG middle temporal gyrus,155
+156,Right OCP occipital pole,156
+157,Left OCP occipital pole,157
+160,Right OFuG occipital fusiform gyrus,160
+161,Left OFuG occipital fusiform gyrus,161
+162,Right OpIFG opercular part of the inferior frontal gyrus,162
+163,Left OpIFG opercular part of the inferior frontal gyrus,163
+164,Right OrIFG orbital part of the inferior frontal gyrus,164
+165,Left OrIFG orbital part of the inferior frontal gyrus,165
+166,Right PCgG posterior cingulate gyrus,166
+167,Left PCgG posterior cingulate gyrus,167
+168,Right PCu precuneus,168
+169,Left PCu precuneus,169
+170,Right PHG parahippocampal gyrus,170
+171,Left PHG parahippocampal gyrus,171
+172,Right PIns posterior insula,172
+173,Left PIns posterior insula,173
+174,Right PO parietal operculum,174
+175,Left PO parietal operculum,175
+176,Right PoG postcentral gyrus,176
+177,Left PoG postcentral gyrus,177
+178,Right POrG posterior orbital gyrus,178
+179,Left POrG posterior orbital gyrus,179
+180,Right PP planum polare,180
+181,Left PP planum polare,181
+182,Right PrG precentral gyrus,182
+183,Left PrG precentral gyrus,183
+184,Right PT planum temporale,184
+185,Left PT planum temporale,185
+186,Right SCA subcallosal area,186
+187,Left SCA subcallosal area,187
+190,Right SFG superior frontal gyrus,190
+191,Left SFG superior frontal gyrus,191
+192,Right SMC supplementary motor cortex,192
+193,Left SMC supplementary motor cortex,193
+194,Right SMG supramarginal gyrus,194
+195,Left SMG supramarginal gyrus,195
+196,Right SOG superior occipital gyrus,196
+197,Left SOG superior occipital gyrus,197
+198,Right SPL superior parietal lobule,198
+199,Left SPL superior parietal lobule,199
+200,Right STG superior temporal gyrus,200
+201,Left STG superior temporal gyrus,201
+202,Right TMP temporal pole,202
+203,Left TMP temporal pole,203
+204,Right TrIFG triangular part of the inferior frontal gyrus,204
+205,Left TrIFG triangular part of the inferior frontal gyrus,205
+206,Right TTG transverse temporal gyrus,206
+207,Left TTG transverse temporal gyrus,207
diff --git a/NiBAx/core/MUSE_ROI_Dictionary.csv b/NiBAx/core/MUSE_ROI_Dictionary.csv
new file mode 100644
index 000000000..f68431034
--- /dev/null
+++ b/NiBAx/core/MUSE_ROI_Dictionary.csv
@@ -0,0 +1,263 @@
+ROI_COL,ROI_INDEX,ROI_LEVEL,ROI_NAME,NUM_VOX,HEMISPHERE,TISSUE_SEG,SUBGROUP_0,SUBGROUP_1,SUBGROUP_2,PAIR_INDEX
+MUSE_Volume_4,4,SINGLE,3rd Ventricle,636.8,B,VN,VENTRICLE,VENTRICLE,VENTRICLE,0
+MUSE_Volume_11,11,SINGLE,4th Ventricle,1959.6,B,VN,VENTRICLE,VENTRICLE,VENTRICLE,0
+MUSE_Volume_23,23,SINGLE,Right Accumbens Area,526,R,GM,DEEP_WM_GM,BASAL_GANGLIA,BASAL_GANGLIA,3
+MUSE_Volume_30,30,SINGLE,Left Accumbens Area,585.9,L,GM,DEEP_WM_GM,BASAL_GANGLIA,BASAL_GANGLIA,3
+MUSE_Volume_31,31,SINGLE,Right Amygdala,1021.3,R,GM,DEEP_WM_GM,Right Amygdala,Right Amygdala,11
+MUSE_Volume_32,32,SINGLE,Left Amygdala,993.7,L,GM,DEEP_WM_GM,Left Amygdala,Left Amygdala,11
+MUSE_Volume_35,35,SINGLE,Brain Stem,18491.6,B,NONE,NONE,NONE,NONE,0
+MUSE_Volume_36,36,SINGLE,Right Caudate,3651.5,R,GM,DEEP_WM_GM,BASAL_GANGLIA,BASAL_GANGLIA,4
+MUSE_Volume_37,37,SINGLE,Left Caudate,3578.9,L,GM,DEEP_WM_GM,BASAL_GANGLIA,BASAL_GANGLIA,4
+MUSE_Volume_38,38,SINGLE,Right Cerebellum Exterior,54379.4,R,GM,CEREBELLUM,CEREBELLUM,CEREBELLUM,1
+MUSE_Volume_39,39,SINGLE,Left Cerebellum Exterior,54582.6,L,GM,CEREBELLUM,CEREBELLUM,CEREBELLUM,1
+MUSE_Volume_40,40,SINGLE,Right Cerebellum White Matter,15458.7,R,WM,CEREBELLUM,CEREBELLUM,CEREBELLUM,2
+MUSE_Volume_41,41,SINGLE,Left Cerebellum White Matter,15500.7,L,WM,CEREBELLUM,CEREBELLUM,CEREBELLUM,2
+MUSE_Volume_46,46,SINGLE,CSF,1011.6,B,CSF,NONE,NONE,NONE,0
+MUSE_Volume_47,47,SINGLE,Right Hippocampus,3704.7,R,GM,DEEP_WM_GM,Right Hippocampus,Right Hippocampus,13
+MUSE_Volume_48,48,SINGLE,Left Hippocampus,3597.7,L,GM,DEEP_WM_GM,Left Hippocampus,Left Hippocampus,13
+MUSE_Volume_49,49,SINGLE,Right Inf Lat Vent,352.9,R,VN,VENTRICLE,VENTRICLE,VENTRICLE,67
+MUSE_Volume_50,50,SINGLE,Left Inf Lat Vent,304.9,L,VN,VENTRICLE,VENTRICLE,VENTRICLE,67
+MUSE_Volume_51,51,SINGLE,Right Lateral Ventricle,6629.5,R,VN,VENTRICLE,VENTRICLE,VENTRICLE,68
+MUSE_Volume_52,52,SINGLE,Left Lateral Ventricle,7954.9,L,VN,VENTRICLE,VENTRICLE,VENTRICLE,68
+MUSE_Volume_55,55,SINGLE,Right Pallidum,1638.8,R,GM,DEEP_WM_GM,BASAL_GANGLIA,BASAL_GANGLIA,5
+MUSE_Volume_56,56,SINGLE,Left Pallidum,1597.6,L,GM,DEEP_WM_GM,BASAL_GANGLIA,BASAL_GANGLIA,5
+MUSE_Volume_57,57,SINGLE,Right Putamen,4726,R,GM,DEEP_WM_GM,BASAL_GANGLIA,BASAL_GANGLIA,6
+MUSE_Volume_58,58,SINGLE,Left Putamen,4942.3,L,GM,DEEP_WM_GM,BASAL_GANGLIA,BASAL_GANGLIA,6
+MUSE_Volume_59,59,SINGLE,Right Thalamus Proper,8256.3,R,GM,DEEP_WM_GM,DEEP_GM,DEEP_GM,7
+MUSE_Volume_60,60,SINGLE,Left Thalamus Proper,8574.1,L,GM,DEEP_WM_GM,DEEP_GM,DEEP_GM,7
+MUSE_Volume_61,61,SINGLE,Right Ventral DC,4998.9,R,NONE,NONE,NONE,NONE,69
+MUSE_Volume_62,62,SINGLE,Left Ventral DC,5192.8,L,NONE,NONE,NONE,NONE,69
+MUSE_Volume_63,63,SINGLE,Right vessel,33.3,R,NONE,NONE,NONE,NONE,70
+MUSE_Volume_64,64,SINGLE,Left vessel,36.5,L,NONE,NONE,NONE,NONE,70
+MUSE_Volume_71,71,SINGLE,Cerebellar Vermal Lobules I-V,4899.8,B,GM,CEREBELLUM,CEREBELLUM,CEREBELLUM,0
+MUSE_Volume_72,72,SINGLE,Cerebellar Vermal Lobules VI-VII,2266.9,B,GM,CEREBELLUM,CEREBELLUM,CEREBELLUM,0
+MUSE_Volume_73,73,SINGLE,Cerebellar Vermal Lobules VIII-X,2858.8,B,GM,CEREBELLUM,CEREBELLUM,CEREBELLUM,0
+MUSE_Volume_75,75,SINGLE,Left Basal Forebrain,586.5,L,GM,DEEP_WM_GM,Left Basal Forebrain,Left Basal Forebrain,12
+MUSE_Volume_76,76,SINGLE,Right Basal Forebrain,593.1,R,GM,DEEP_WM_GM,Right Basal Forebrain,Right Basal Forebrain,12
+MUSE_Volume_81,81,SINGLE,frontal lobe WM right,95088,R,WM,FRONTAL,FRONTAL_WM,FRONTAL_WM,36
+MUSE_Volume_82,82,SINGLE,frontal lobe WM left,91872,L,WM,FRONTAL,FRONTAL_WM,FRONTAL_WM,36
+MUSE_Volume_83,83,SINGLE,occipital lobe WM right,22798.8,R,WM,OCCIPITAL,OCCIPITAL_WM,OCCIPITAL_WM,50
+MUSE_Volume_84,84,SINGLE,occipital lobe WM left,22741.6,L,WM,OCCIPITAL,OCCIPITAL_WM,OCCIPITAL_WM,50
+MUSE_Volume_85,85,SINGLE,parietal lobe WM right,44216.6,R,WM,PARIETAL,PARIETAL_WM,PARIETAL_WM,57
+MUSE_Volume_86,86,SINGLE,parietal lobe WM left,47236.9,L,WM,PARIETAL,PARIETAL_WM,PARIETAL_WM,57
+MUSE_Volume_87,87,SINGLE,temporal lobe WM right,55390.7,R,WM,TEMPORAL,TEMPORAL_WM,TEMPORAL_WM,66
+MUSE_Volume_88,88,SINGLE,temporal lobe WM left,54535.2,L,WM,TEMPORAL,TEMPORAL_WM,TEMPORAL_WM,66
+MUSE_Volume_89,89,SINGLE,fornix right,517.5,R,WM,DEEP_WM_GM,DEEP_WM,DEEP_WM,9
+MUSE_Volume_90,90,SINGLE,fornix left,673.6,L,WM,DEEP_WM_GM,DEEP_WM,DEEP_WM,9
+MUSE_Volume_91,91,SINGLE,anterior limb of internal capsule right,3393.3,R,WM,DEEP_WM_GM,DEEP_WM,DEEP_WM,8
+MUSE_Volume_92,92,SINGLE,anterior limb of internal capsule left,2887.7,L,WM,DEEP_WM_GM,DEEP_WM,DEEP_WM,8
+MUSE_Volume_93,93,SINGLE,posterior limb of internal capsule inc. cerebral peduncle right,2480.5,R,WM,DEEP_WM_GM,DEEP_WM,DEEP_WM,10
+MUSE_Volume_94,94,SINGLE,posterior limb of internal capsule inc. cerebral peduncle left,2416.3,L,WM,DEEP_WM_GM,DEEP_WM,DEEP_WM,10
+MUSE_Volume_95,95,SINGLE,corpus callosum,12871.8,B,WM,NONE,NONE,NONE,0
+MUSE_Volume_100,100,SINGLE,Right ACgG anterior cingulate gyrus,4782.3,R,GM,LIMBIC,LIMBIC_GM,LIMBIC_CINGULATE_GM,37
+MUSE_Volume_101,101,SINGLE,Left ACgG anterior cingulate gyrus,5262.2,L,GM,LIMBIC,LIMBIC_GM,LIMBIC_CINGULATE_GM,37
+MUSE_Volume_102,102,SINGLE,Right AIns anterior insula,4600.1,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_INSULAR_GM,18
+MUSE_Volume_103,103,SINGLE,Left AIns anterior insula,4749.1,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_INSULAR_GM,18
+MUSE_Volume_104,104,SINGLE,Right AOrG anterior orbital gyrus,2244.9,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_INFERIOR_GM,14
+MUSE_Volume_105,105,SINGLE,Left AOrG anterior orbital gyrus,1897.7,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_INFERIOR_GM,14
+MUSE_Volume_106,106,SINGLE,Right AnG angular gyrus,11563.6,R,GM,PARIETAL,PARIETAL_GM,PARIETAL_LATERAL_GM,51
+MUSE_Volume_107,107,SINGLE,Left AnG angular gyrus,9939.4,L,GM,PARIETAL,PARIETAL_GM,PARIETAL_LATERAL_GM,51
+MUSE_Volume_108,108,SINGLE,Right Calc calcarine cortex,3543.7,R,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_MEDIAL_GM,47
+MUSE_Volume_109,109,SINGLE,Left Calc calcarine cortex,3635.5,L,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_MEDIAL_GM,47
+MUSE_Volume_112,112,SINGLE,Right CO central operculum,4691.3,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_OPERCULAR_GM,33
+MUSE_Volume_113,113,SINGLE,Left CO central operculum,4466.1,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_OPERCULAR_GM,33
+MUSE_Volume_114,114,SINGLE,Right Cun cuneus,5884.9,R,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_MEDIAL_GM,48
+MUSE_Volume_115,115,SINGLE,Left Cun cuneus,5314.7,L,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_MEDIAL_GM,48
+MUSE_Volume_116,116,SINGLE,Right Ent entorhinal area,2120.6,R,GM,LIMBIC,LIMBIC_GM,LIMBIC_MEDIALTEMPORAL_GM,40
+MUSE_Volume_117,117,SINGLE,Left Ent entorhinal area,1887.4,L,GM,LIMBIC,LIMBIC_GM,LIMBIC_MEDIALTEMPORAL_GM,40
+MUSE_Volume_118,118,SINGLE,Right FO frontal operculum,2548.3,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_OPERCULAR_GM,34
+MUSE_Volume_119,119,SINGLE,Left FO frontal operculum,2489.9,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_OPERCULAR_GM,34
+MUSE_Volume_120,120,SINGLE,Right FRP frontal pole,4673.7,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_LATERAL_GM,20
+MUSE_Volume_121,121,SINGLE,Left FRP frontal pole,4392.8,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_LATERAL_GM,20
+MUSE_Volume_122,122,SINGLE,Right FuG fusiform gyrus,8000.9,R,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_INFERIOR_GM,58
+MUSE_Volume_123,123,SINGLE,Left FuG fusiform gyrus,8077.2,L,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_INFERIOR_GM,58
+MUSE_Volume_124,124,SINGLE,Right GRe gyrus rectus,2699.9,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_MEDIAL_GM,27
+MUSE_Volume_125,125,SINGLE,Left GRe gyrus rectus,2920.3,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_MEDIAL_GM,27
+MUSE_Volume_128,128,SINGLE,Right IOG inferior occipital gyrus,7633,R,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_LATERAL_GM,43
+MUSE_Volume_129,129,SINGLE,Left IOG inferior occipital gyrus,7403.4,L,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_LATERAL_GM,43
+MUSE_Volume_132,132,SINGLE,Right ITG inferior temporal gyrus,12693.2,R,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_LATERAL_GM,59
+MUSE_Volume_133,133,SINGLE,Left ITG inferior temporal gyrus,12612.3,L,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_LATERAL_GM,59
+MUSE_Volume_134,134,SINGLE,Right LiG lingual gyrus,8366,R,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_MEDIAL_GM,49
+MUSE_Volume_135,135,SINGLE,Left LiG lingual gyrus,8386.3,L,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_MEDIAL_GM,49
+MUSE_Volume_136,136,SINGLE,Right LOrG lateral orbital gyrus,2864.1,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_INFERIOR_GM,15
+MUSE_Volume_137,137,SINGLE,Left LOrG lateral orbital gyrus,3015.9,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_INFERIOR_GM,15
+MUSE_Volume_138,138,SINGLE,Right MCgG middle cingulate gyrus,5475.1,R,GM,LIMBIC,LIMBIC_GM,LIMBIC_CINGULATE_GM,38
+MUSE_Volume_139,139,SINGLE,Left MCgG middle cingulate gyrus,5335.1,L,GM,LIMBIC,LIMBIC_GM,LIMBIC_CINGULATE_GM,38
+MUSE_Volume_140,140,SINGLE,Right MFC medial frontal cortex,2202.6,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_MEDIAL_GM,28
+MUSE_Volume_141,141,SINGLE,Left MFC medial frontal cortex,2245.2,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_MEDIAL_GM,28
+MUSE_Volume_142,142,SINGLE,Right MFG middle frontal gyrus,22580.4,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_LATERAL_GM,21
+MUSE_Volume_143,143,SINGLE,Left MFG middle frontal gyrus,22847.3,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_LATERAL_GM,21
+MUSE_Volume_144,144,SINGLE,Right MOG middle occipital gyrus,6792.1,R,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_LATERAL_GM,44
+MUSE_Volume_145,145,SINGLE,Left MOG middle occipital gyrus,7232.9,L,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_LATERAL_GM,44
+MUSE_Volume_146,146,SINGLE,Right MOrG medial orbital gyrus,4526.7,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_INFERIOR_GM,16
+MUSE_Volume_147,147,SINGLE,Left MOrG medial orbital gyrus,4637.3,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_INFERIOR_GM,16
+MUSE_Volume_148,148,SINGLE,Right MPoG postcentral gyrus medial segment,1162.5,R,GM,PARIETAL,PARIETAL_GM,PARIETAL_MEDIAL_GM,55
+MUSE_Volume_149,149,SINGLE,Left MPoG postcentral gyrus medial segment,1400.3,L,GM,PARIETAL,PARIETAL_GM,PARIETAL_MEDIAL_GM,55
+MUSE_Volume_150,150,SINGLE,Right MPrG precentral gyrus medial segment,2944.5,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_MEDIAL_GM,29
+MUSE_Volume_151,151,SINGLE,Left MPrG precentral gyrus medial segment,3081.3,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_MEDIAL_GM,29
+MUSE_Volume_152,152,SINGLE,Right MSFG superior frontal gyrus medial segment,9415.8,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_MEDIAL_GM,30
+MUSE_Volume_153,153,SINGLE,Left MSFG superior frontal gyrus medial segment,8737,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_MEDIAL_GM,30
+MUSE_Volume_154,154,SINGLE,Right MTG middle temporal gyrus,16084.6,R,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_LATERAL_GM,60
+MUSE_Volume_155,155,SINGLE,Left MTG middle temporal gyrus,15793.8,L,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_LATERAL_GM,60
+MUSE_Volume_156,156,SINGLE,Right OCP occipital pole,4054.5,R,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_LATERAL_GM,45
+MUSE_Volume_157,157,SINGLE,Left OCP occipital pole,4297.6,L,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_LATERAL_GM,45
+MUSE_Volume_160,160,SINGLE,Right OFuG occipital fusiform gyrus,4857.3,R,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_INFERIOR_GM,42
+MUSE_Volume_161,161,SINGLE,Left OFuG occipital fusiform gyrus,5087.5,L,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_INFERIOR_GM,42
+MUSE_Volume_162,162,SINGLE,Right OpIFG opercular part of the inferior frontal gyrus,4094.1,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_LATERAL_GM,22
+MUSE_Volume_163,163,SINGLE,Left OpIFG opercular part of the inferior frontal gyrus,3747,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_LATERAL_GM,22
+MUSE_Volume_164,164,SINGLE,Right OrIFG orbital part of the inferior frontal gyrus,1944.4,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_LATERAL_GM,23
+MUSE_Volume_165,165,SINGLE,Left OrIFG orbital part of the inferior frontal gyrus,1901.2,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_LATERAL_GM,23
+MUSE_Volume_166,166,SINGLE,Right PCgG posterior cingulate gyrus,4324.3,R,GM,LIMBIC,LIMBIC_GM,LIMBIC_CINGULATE_GM,39
+MUSE_Volume_167,167,SINGLE,Left PCgG posterior cingulate gyrus,5181.6,L,GM,LIMBIC,LIMBIC_GM,LIMBIC_CINGULATE_GM,39
+MUSE_Volume_168,168,SINGLE,Right PCu precuneus,11732.1,R,GM,PARIETAL,PARIETAL_GM,PARIETAL_MEDIAL_GM,56
+MUSE_Volume_169,169,SINGLE,Left PCu precuneus,11737.4,L,GM,PARIETAL,PARIETAL_GM,PARIETAL_MEDIAL_GM,56
+MUSE_Volume_170,170,SINGLE,Right PHG parahippocampal gyrus,3257.5,R,GM,LIMBIC,LIMBIC_GM,LIMBIC_MEDIALTEMPORAL_GM,41
+MUSE_Volume_171,171,SINGLE,Left PHG parahippocampal gyrus,3536.5,L,GM,LIMBIC,LIMBIC_GM,LIMBIC_MEDIALTEMPORAL_GM,41
+MUSE_Volume_172,172,SINGLE,Right PIns posterior insula,2532,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_INSULAR_GM,19
+MUSE_Volume_173,173,SINGLE,Left PIns posterior insula,2479.5,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_INSULAR_GM,19
+MUSE_Volume_174,174,SINGLE,Right PO parietal operculum,2414.5,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_OPERCULAR_GM,35
+MUSE_Volume_175,175,SINGLE,Left PO parietal operculum,2768.9,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_OPERCULAR_GM,35
+MUSE_Volume_176,176,SINGLE,Right PoG postcentral gyrus,11680.7,R,GM,PARIETAL,PARIETAL_GM,PARIETAL_LATERAL_GM,52
+MUSE_Volume_177,177,SINGLE,Left PoG postcentral gyrus,13593.5,L,GM,PARIETAL,PARIETAL_GM,PARIETAL_LATERAL_GM,52
+MUSE_Volume_178,178,SINGLE,Right POrG posterior orbital gyrus,2504.8,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_INFERIOR_GM,17
+MUSE_Volume_179,179,SINGLE,Left POrG posterior orbital gyrus,2915.7,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_INFERIOR_GM,17
+MUSE_Volume_180,180,SINGLE,Right PP planum polare,2448.5,R,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_SUPRATEMPORAL_GM,63
+MUSE_Volume_181,181,SINGLE,Left PP planum polare,2629.8,L,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_SUPRATEMPORAL_GM,63
+MUSE_Volume_182,182,SINGLE,Right PrG precentral gyrus,14641.2,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_LATERAL_GM,24
+MUSE_Volume_183,183,SINGLE,Left PrG precentral gyrus,14664.6,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_LATERAL_GM,24
+MUSE_Volume_184,184,SINGLE,Right PT planum temporale,2325.5,R,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_SUPRATEMPORAL_GM,64
+MUSE_Volume_185,185,SINGLE,Left PT planum temporale,2511.3,L,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_SUPRATEMPORAL_GM,64
+MUSE_Volume_186,186,SINGLE,Right SCA subcallosal area,1236,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_MEDIAL_GM,31
+MUSE_Volume_187,187,SINGLE,Left SCA subcallosal area,1220.8,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_MEDIAL_GM,31
+MUSE_Volume_190,190,SINGLE,Right SFG superior frontal gyrus,16696.7,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_LATERAL_GM,25
+MUSE_Volume_191,191,SINGLE,Left SFG superior frontal gyrus,16867,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_LATERAL_GM,25
+MUSE_Volume_192,192,SINGLE,Right SMC supplementary motor cortex,6368.8,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_MEDIAL_GM,32
+MUSE_Volume_193,193,SINGLE,Left SMC supplementary motor cortex,6723.3,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_MEDIAL_GM,32
+MUSE_Volume_194,194,SINGLE,Right SMG supramarginal gyrus,9193,R,GM,PARIETAL,PARIETAL_GM,PARIETAL_LATERAL_GM,53
+MUSE_Volume_195,195,SINGLE,Left SMG supramarginal gyrus,9984.3,L,GM,PARIETAL,PARIETAL_GM,PARIETAL_LATERAL_GM,53
+MUSE_Volume_196,196,SINGLE,Right SOG superior occipital gyrus,4967,R,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_LATERAL_GM,46
+MUSE_Volume_197,197,SINGLE,Left SOG superior occipital gyrus,4152,L,GM,OCCIPITAL,OCCIPITAL_GM,OCCIPITAL_LATERAL_GM,46
+MUSE_Volume_198,198,SINGLE,Right SPL superior parietal lobule,11792.1,R,GM,PARIETAL,PARIETAL_GM,PARIETAL_LATERAL_GM,54
+MUSE_Volume_199,199,SINGLE,Left SPL superior parietal lobule,11732.8,L,GM,PARIETAL,PARIETAL_GM,PARIETAL_LATERAL_GM,54
+MUSE_Volume_200,200,SINGLE,Right STG superior temporal gyrus,9031.2,R,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_LATERAL_GM,61
+MUSE_Volume_201,201,SINGLE,Left STG superior temporal gyrus,8451.3,L,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_LATERAL_GM,61
+MUSE_Volume_202,202,SINGLE,Right TMP temporal pole,8883.7,R,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_LATERAL_GM,62
+MUSE_Volume_203,203,SINGLE,Left TMP temporal pole,8632.1,L,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_LATERAL_GM,62
+MUSE_Volume_204,204,SINGLE,Right TrIFG triangular part of the inferior frontal gyrus,4522.4,R,GM,FRONTAL,FRONTAL_GM,FRONTAL_LATERAL_GM,26
+MUSE_Volume_205,205,SINGLE,Left TrIFG triangular part of the inferior frontal gyrus,5256.2,L,GM,FRONTAL,FRONTAL_GM,FRONTAL_LATERAL_GM,26
+MUSE_Volume_206,206,SINGLE,Right TTG transverse temporal gyrus,1529.1,R,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_SUPRATEMPORAL_GM,65
+MUSE_Volume_207,207,SINGLE,Left TTG transverse temporal gyrus,1821.1,L,GM,TEMPORAL,TEMPORAL_GM,TEMPORAL_SUPRATEMPORAL_GM,65
+MUSE_Volume_301,301,DERIVED,FRONTAL_INFERIOR_GM,,,,,,,
+MUSE_Volume_302,302,DERIVED,FRONTAL_INSULAR_GM,,,,,,,
+MUSE_Volume_303,303,DERIVED,FRONTAL_LATERAL_GM,,,,,,,
+MUSE_Volume_304,304,DERIVED,FRONTAL_MEDIAL_GM,,,,,,,
+MUSE_Volume_305,305,DERIVED,FRONTAL_OPERCULAR_GM,,,,,,,
+MUSE_Volume_306,306,DERIVED,LIMBIC_CINGULATE_GM,,,,,,,
+MUSE_Volume_307,307,DERIVED,LIMBIC_MEDIALTEMPORAL_GM,,,,,,,
+MUSE_Volume_308,308,DERIVED,OCCIPITAL_INFERIOR_GM,,,,,,,
+MUSE_Volume_309,309,DERIVED,OCCIPITAL_LATERAL_GM,,,,,,,
+MUSE_Volume_310,310,DERIVED,OCCIPITAL_MEDIAL_GM,,,,,,,
+MUSE_Volume_311,311,DERIVED,PARIETAL_LATERAL_GM,,,,,,,
+MUSE_Volume_312,312,DERIVED,PARIETAL_MEDIAL_GM,,,,,,,
+MUSE_Volume_313,313,DERIVED,TEMPORAL_INFERIOR_GM,,,,,,,
+MUSE_Volume_314,314,DERIVED,TEMPORAL_LATERAL_GM,,,,,,,
+MUSE_Volume_315,315,DERIVED,TEMPORAL_SUPRATEMPORAL_GM,,,,,,,
+MUSE_Volume_316,316,DERIVED,FRONTAL_INFERIOR_GM_L,,,,,,,
+MUSE_Volume_317,317,DERIVED,FRONTAL_INSULAR_GM_L,,,,,,,
+MUSE_Volume_318,318,DERIVED,FRONTAL_LATERAL_GM_L,,,,,,,
+MUSE_Volume_319,319,DERIVED,FRONTAL_MEDIAL_GM_L,,,,,,,
+MUSE_Volume_320,320,DERIVED,FRONTAL_OPERCULAR_GM_L,,,,,,,
+MUSE_Volume_321,321,DERIVED,LIMBIC_CINGULATE_GM_L,,,,,,,
+MUSE_Volume_322,322,DERIVED,LIMBIC_MEDIALTEMPORAL_GM_L,,,,,,,
+MUSE_Volume_323,323,DERIVED,OCCIPITAL_INFERIOR_GM_L,,,,,,,
+MUSE_Volume_324,324,DERIVED,OCCIPITAL_LATERAL_GM_L,,,,,,,
+MUSE_Volume_325,325,DERIVED,OCCIPITAL_MEDIAL_GM_L,,,,,,,
+MUSE_Volume_326,326,DERIVED,PARIETAL_LATERAL_GM_L,,,,,,,
+MUSE_Volume_327,327,DERIVED,PARIETAL_MEDIAL_GM_L,,,,,,,
+MUSE_Volume_328,328,DERIVED,TEMPORAL_INFERIOR_GM_L,,,,,,,
+MUSE_Volume_329,329,DERIVED,TEMPORAL_LATERAL_GM_L,,,,,,,
+MUSE_Volume_330,330,DERIVED,TEMPORAL_SUPRATEMPORAL_GM_L,,,,,,,
+MUSE_Volume_331,331,DERIVED,FRONTAL_INFERIOR_GM_R,,,,,,,
+MUSE_Volume_332,332,DERIVED,FRONTAL_INSULAR_GM_R,,,,,,,
+MUSE_Volume_333,333,DERIVED,FRONTAL_LATERAL_GM_R,,,,,,,
+MUSE_Volume_334,334,DERIVED,FRONTAL_MEDIAL_GM_R,,,,,,,
+MUSE_Volume_335,335,DERIVED,FRONTAL_OPERCULAR_GM_R,,,,,,,
+MUSE_Volume_336,336,DERIVED,LIMBIC_CINGULATE_GM_R,,,,,,,
+MUSE_Volume_337,337,DERIVED,LIMBIC_MEDIALTEMPORAL_GM_R,,,,,,,
+MUSE_Volume_338,338,DERIVED,OCCIPITAL_INFERIOR_GM_R,,,,,,,
+MUSE_Volume_339,339,DERIVED,OCCIPITAL_LATERAL_GM_R,,,,,,,
+MUSE_Volume_340,340,DERIVED,OCCIPITAL_MEDIAL_GM_R,,,,,,,
+MUSE_Volume_341,341,DERIVED,PARIETAL_LATERAL_GM_R,,,,,,,
+MUSE_Volume_342,342,DERIVED,PARIETAL_MEDIAL_GM_R,,,,,,,
+MUSE_Volume_343,343,DERIVED,TEMPORAL_INFERIOR_GM_R,,,,,,,
+MUSE_Volume_344,344,DERIVED,TEMPORAL_LATERAL_GM_R,,,,,,,
+MUSE_Volume_345,345,DERIVED,TEMPORAL_SUPRATEMPORAL_GM_R,,,,,,,
+MUSE_Volume_401,401,DERIVED,BASAL_GANGLIA,,,,,,,
+MUSE_Volume_402,402,DERIVED,DEEP_GM,,,,,,,
+MUSE_Volume_403,403,DERIVED,DEEP_WM,,,,,,,
+MUSE_Volume_404,404,DERIVED,FRONTAL_GM,,,,,,,
+MUSE_Volume_405,405,DERIVED,FRONTAL_WM,,,,,,,
+MUSE_Volume_406,406,DERIVED,LIMBIC_GM,,,,,,,
+MUSE_Volume_407,407,DERIVED,OCCIPITAL_GM,,,,,,,
+MUSE_Volume_408,408,DERIVED,OCCIPITAL_WM,,,,,,,
+MUSE_Volume_409,409,DERIVED,PARIETAL_GM,,,,,,,
+MUSE_Volume_410,410,DERIVED,PARIETAL_WM,,,,,,,
+MUSE_Volume_411,411,DERIVED,TEMPORAL_GM,,,,,,,
+MUSE_Volume_412,412,DERIVED,TEMPORAL_WM,,,,,,,
+MUSE_Volume_413,413,DERIVED,BASAL_GANGLIA_L,,,,,,,
+MUSE_Volume_414,414,DERIVED,DEEP_GM_L,,,,,,,
+MUSE_Volume_415,415,DERIVED,DEEP_WM_L,,,,,,,
+MUSE_Volume_416,416,DERIVED,FRONTAL_GM_L,,,,,,,
+MUSE_Volume_417,417,DERIVED,FRONTAL_WM_L,,,,,,,
+MUSE_Volume_418,418,DERIVED,LIMBIC_GM_L,,,,,,,
+MUSE_Volume_419,419,DERIVED,OCCIPITAL_GM_L,,,,,,,
+MUSE_Volume_420,420,DERIVED,OCCIPITAL_WM_L,,,,,,,
+MUSE_Volume_421,421,DERIVED,PARIETAL_GM_L,,,,,,,
+MUSE_Volume_422,422,DERIVED,PARIETAL_WM_L,,,,,,,
+MUSE_Volume_423,423,DERIVED,TEMPORAL_GM_L,,,,,,,
+MUSE_Volume_424,424,DERIVED,TEMPORAL_WM_L,,,,,,,
+MUSE_Volume_425,425,DERIVED,BASAL_GANGLIA_R,,,,,,,
+MUSE_Volume_426,426,DERIVED,DEEP_GM_R,,,,,,,
+MUSE_Volume_427,427,DERIVED,DEEP_WM_R,,,,,,,
+MUSE_Volume_428,428,DERIVED,FRONTAL_GM_R,,,,,,,
+MUSE_Volume_429,429,DERIVED,FRONTAL_WM_R,,,,,,,
+MUSE_Volume_430,430,DERIVED,LIMBIC_GM_R,,,,,,,
+MUSE_Volume_431,431,DERIVED,OCCIPITAL_GM_R,,,,,,,
+MUSE_Volume_432,432,DERIVED,OCCIPITAL_WM_R,,,,,,,
+MUSE_Volume_433,433,DERIVED,PARIETAL_GM_R,,,,,,,
+MUSE_Volume_434,434,DERIVED,PARIETAL_WM_R,,,,,,,
+MUSE_Volume_435,435,DERIVED,TEMPORAL_GM_R,,,,,,,
+MUSE_Volume_436,436,DERIVED,TEMPORAL_WM_R,,,,,,,
+MUSE_Volume_501,501,DERIVED,CORPUS_CALLOSUM,,,,,,,
+MUSE_Volume_502,502,DERIVED,CEREBELLUM,,,,,,,
+MUSE_Volume_503,503,DERIVED,DEEP_WM_GM,,,,,,,
+MUSE_Volume_504,504,DERIVED,FRONTAL,,,,,,,
+MUSE_Volume_505,505,DERIVED,LIMBIC,,,,,,,
+MUSE_Volume_506,506,DERIVED,OCCIPITAL,,,,,,,
+MUSE_Volume_507,507,DERIVED,PARIETAL,,,,,,,
+MUSE_Volume_508,508,DERIVED,TEMPORAL,,,,,,,
+MUSE_Volume_509,509,DERIVED,VENTRICLE,,,,,,,
+MUSE_Volume_510,510,DERIVED,CEREBELLUM_L,,,,,,,
+MUSE_Volume_511,511,DERIVED,DEEP_WM_GM_L,,,,,,,
+MUSE_Volume_512,512,DERIVED,FRONTAL_L,,,,,,,
+MUSE_Volume_513,513,DERIVED,LIMBIC_L,,,,,,,
+MUSE_Volume_514,514,DERIVED,OCCIPITAL_L,,,,,,,
+MUSE_Volume_515,515,DERIVED,PARIETAL_L,,,,,,,
+MUSE_Volume_516,516,DERIVED,TEMPORAL_L,,,,,,,
+MUSE_Volume_517,517,DERIVED,VENTRICLE_L,,,,,,,
+MUSE_Volume_518,518,DERIVED,CEREBELLUM_R,,,,,,,
+MUSE_Volume_519,519,DERIVED,DEEP_WM_GM_R,,,,,,,
+MUSE_Volume_520,520,DERIVED,FRONTAL_R,,,,,,,
+MUSE_Volume_521,521,DERIVED,LIMBIC_R,,,,,,,
+MUSE_Volume_522,522,DERIVED,OCCIPITAL_R,,,,,,,
+MUSE_Volume_523,523,DERIVED,PARIETAL_R,,,,,,,
+MUSE_Volume_524,524,DERIVED,TEMPORAL_R,,,,,,,
+MUSE_Volume_525,525,DERIVED,VENTRICLE_R,,,,,,,
+MUSE_Volume_601,601,DERIVED,GM,,,,,,,
+MUSE_Volume_604,604,DERIVED,WM,,,,,,,
+MUSE_Volume_606,606,DERIVED,GM_L,,,,,,,
+MUSE_Volume_607,607,DERIVED,WM_L,,,,,,,
+MUSE_Volume_613,613,DERIVED,GM_R,,,,,,,
+MUSE_Volume_614,614,DERIVED,WM_R,,,,,,,
+MUSE_Volume_701,701,DERIVED,TOTALBRAIN,,,,,,,
+MUSE_Volume_702,702,DERIVED,ICV,,,,,,,
\ No newline at end of file
diff --git a/NiBAx/core/dataio.py b/NiBAx/core/dataio.py
new file mode 100644
index 000000000..54efe03ff
--- /dev/null
+++ b/NiBAx/core/dataio.py
@@ -0,0 +1,67 @@
+# This Python file uses the following encoding: utf-8
+"""
+contact: software@cbica.upenn.edu
+Copyright (c) 2018 University of Pennsylvania. All rights reserved.
+Use of this source code is governed by license located in license file: https://github.com/CBICA/NiBAx/blob/main/LICENSE
+"""
+
+import pandas as pd
+import joblib
+import os, sys
+from NiBAx.core import iStagingLogger
+
+logger = iStagingLogger.get_logger(__name__)
+
+class DataIO:
+ def __init__(self):
+ pass
+
+
+ def ReadPickleFile(self,filename):
+ logger.info("Loading pickle file ...")
+ data = pd.read_pickle(filename)
+ return data
+
+
+ def ReadCSVFile(self,filename):
+ logger.info("Loading CSV file ...")
+ data = pd.read_csv(filename)
+ return data
+
+
+ def SavePickleFile(self,data,filename):
+ data.to_pickle(filename)
+
+ def ReadMUSEDictionary(self):
+ # Load MUSE dictionary file
+ MUSEDictfile = os.path.join(os.path.dirname(__file__), 'MUSE_ROI_Dictionary.csv')
+ MUSEDict = pd.read_csv(MUSEDictfile)
+
+ # Create lookup from name to ID and vice-versa
+ # e.g. name to ID: Hippocampus right -> MUSE_Volume_48
+ MUSEDictNAMEtoID = dict(zip(MUSEDict['ROI_NAME'], MUSEDict['ROI_COL']))
+ # e.g. ID to name; MUSE_Volume_48 -> Hippocampus right
+ MUSEDictIDtoNAME = dict(zip(MUSEDict['ROI_COL'], MUSEDict['ROI_NAME']))
+
+ MUSEDictDataFrame = MUSEDict
+
+ logger.info('MUSE dictionary read from file: %s', MUSEDictfile)
+
+ return MUSEDictNAMEtoID, MUSEDictIDtoNAME, MUSEDictDataFrame
+
+ def ReadDerivedMUSEMap(self):
+ # Load MUSE dictionary file
+ DerivedMapfile = os.path.join(os.path.dirname(__file__), 'MUSE_DerivedROIs_Mappings.csv')
+ DerivedMUSEMap = pd.read_csv(DerivedMapfile,
+ header=None, engine='python').reset_index().rename(columns={'level_0':'ROI_INDEX','level_1':'ROI_NAME'}).set_index('ROI_INDEX').drop(columns=['ROI_NAME'])
+
+ logger.info('Derived MUSE dictionary read from file: %s', DerivedMapfile)
+
+ return DerivedMUSEMap
+
+
+ def ReadSPAREModel(self, filename):
+ with open(filename, "rb") as file:
+ BrainAgeModel, ADModel = joblib.load(filename)
+
+ return BrainAgeModel, ADModel
diff --git a/NiBAx/core/gui/CheckableQComboBox.py b/NiBAx/core/gui/CheckableQComboBox.py
new file mode 100644
index 000000000..22d9b2c5c
--- /dev/null
+++ b/NiBAx/core/gui/CheckableQComboBox.py
@@ -0,0 +1,43 @@
+# This Python file uses the following encoding: utf-8
+"""
+Author: Ashish Singh
+contact: software@cbica.upenn.edu
+Copyright (c) 2018 University of Pennsylvania. All rights reserved.
+Use of this source code is governed by license located in license file: https://github.com/CBICA/NiBAx/blob/main/LICENSE
+"""
+from PyQt5 import QtCore, QtWidgets
+
+class CheckableQComboBox(QtWidgets.QComboBox):
+
+ def __init__(self, parent=None):
+ super(CheckableQComboBox, self).__init__(parent)
+
+ # once there is a checkState set, it is rendered
+ # here we assume default Unchecked
+ def addItem(self, item):
+ super(CheckableQComboBox, self).addItem(item)
+ item = self.model().item(self.count()-1,0)
+ item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
+ item.setCheckState(QtCore.Qt.Unchecked)
+
+ def addItems(self, items):
+ for i, item in enumerate(items):
+ super(CheckableQComboBox, self).addItem(item)
+ item = self.model().item(self.count()-1,0)
+ item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
+ item.setCheckState(QtCore.Qt.Unchecked)
+ #item.setCheckState(QtCore.Qt.Checked)
+
+ def itemChecked(self, index):
+ item = self.model().item(index,0)
+ return item.checkState() == QtCore.Qt.Checked
+
+ def listCheckedItems(self):
+ sel_list=[]
+ for tmpInd in range(0, self.count()):
+ if self.itemChecked(tmpInd):
+ sel_list.append(self.itemText(tmpInd))
+ return sel_list
+
+ #item = self.model().item(i,0)
+ #return item.checkState() == QtCore.Qt.Checked
diff --git a/NiBAx/core/model/datamodel.py b/NiBAx/core/model/datamodel.py
index c357ce30c..0573f33c2 100644
--- a/NiBAx/core/model/datamodel.py
+++ b/NiBAx/core/model/datamodel.py
@@ -21,11 +21,17 @@ class DataModel(QObject):
"""This class holds the data model."""
data_changed = QtCore.pyqtSignal()
+ currdata_changed = QtCore.pyqtSignal()
def __init__(self):
QObject.__init__(self)
"""The constructor."""
self.data = None
+ self.currdata = None
+ self.datacols = None
+ self.currdatacols = None
+ self.sortCols = []
+ self.sortOrders = []
self.harmonization_model = None
self.MUSEDictNAMEtoID = None
self.MUSEDictIDtoNAME = None
@@ -83,9 +89,24 @@ def GetMUSEDictDataFrame(self):
def SetData(self,d):
"""Setter for data"""
self.data = d
+ self.currdata = d
+
+ self.datacols = d.columns.tolist()
+ self.currdatacols = d.columns.tolist()
+
+ print('Num cols : ' + str(len(self.currdatacols)))
+
logger.info('Data changed in datamodel. Signal emitted.')
self.data_changed.emit()
+ self.currdata_changed.emit()
+ def SetCurrData(self,d):
+ """Setter for data"""
+ self.currdata = d
+ self.currdatacols = d.columns.tolist()
+
+ logger.info('Current data changed in datamodel. Signal emitted.')
+ self.currdata_changed.emit()
def SetHarmonizationModel(self,m):
"""Setter for neuroHarmonize model"""
@@ -100,10 +121,34 @@ def SetSPAREModel(self,BrainAgeModel, ADModel):
self.ADModel = ADModel
- def GetCompleteData(self):
+ def GetData(self):
"""Returns complete data."""
return self.data
+ def GetCurrentData(self):
+ """Returns complete data."""
+ return self.currentdata
+
+ def GetDataSelCols(self, selCols):
+ """Returns sel cols"""
+ d = self.data[selCols]
+ return d
+
+ def GetDataColNames(self):
+ """Returns all header names for all columns in the dataset."""
+ if self.data is not None:
+ k = self.data.keys()
+ else:
+ k = []
+ return k
+
+ def GetCurrDataColNames(self):
+ """Returns all header names for all columns in the dataset."""
+ if self.data is not None:
+ k = self.data.keys()
+ else:
+ k = []
+ return k
def GetModel(self):
"""Returns harmonization model."""
@@ -146,15 +191,16 @@ def GetNormativeRange(self,roi):
return covariates['Age'], y, z
- def GetData(self,roi,hue):
- """Returns a subset of data needed for plot.
- Takes as parameters the roi and hue for the plot.
- Since the plot always uses 'Age' for X axis, this is always returned."""
- if not isinstance(roi, list):
- roi = [roi]
+ #def GetData(self,roi,hue):
+ #"""Returns a subset of data needed for plot.
+ #Takes as parameters the roi and hue for the plot.
+ #Since the plot always uses 'Age' for X axis, this is always returned."""
+ #if not isinstance(roi, list):
+ #roi = [roi]
- d = self.data[roi + ["Age",hue]]
- return d
+ #d = self.data[roi + ["Age",hue]]
+ #return d
+
def IsValidData(self, data=None):
@@ -185,17 +231,14 @@ def IsValidSPARE(self):
#TODO: Implement checks
return True
-
def GetColumnHeaderNames(self):
"""Returns all header names for all columns in the dataset."""
if self.data is not None:
k = self.data.keys()
else:
k = []
-
return k
-
def GetColumnDataTypes(self):
"""Returns all header names for all columns in the dataset."""
d = self.data.dtypes
diff --git a/NiBAx/core/plotcanvas.py b/NiBAx/core/plotcanvas.py
index 80509402e..fb70f3a7e 100644
--- a/NiBAx/core/plotcanvas.py
+++ b/NiBAx/core/plotcanvas.py
@@ -32,7 +32,7 @@ def __init__(self, parent=None, width=5, height=4, dpi=100):
self.setLayout(QtWidgets.QVBoxLayout())
- self.layout().addWidget(self.toolbar)
+ #self.layout().addWidget(self.toolbar)
self.layout().addWidget(self.canvas)
def getFigure(self):
diff --git a/NiBAx/mainwindow.py b/NiBAx/mainwindow.py
index 2ca0201d8..836e189d8 100644
--- a/NiBAx/mainwindow.py
+++ b/NiBAx/mainwindow.py
@@ -9,7 +9,7 @@
from yapsy.PluginManager import PluginManager
from yapsy.IPlugin import IPlugin
import os, sys
-#from BrainChart.dataio import DataIO
+from NiBAx.core.dataio import DataIO
from NiBAx.core.model.datamodel import DataModel
from .aboutdialog import AboutDialog
from NiBAx.resources import resources
@@ -50,6 +50,8 @@ def __init__(self, dataFile=None, harmonizationModelFile=None, SPAREModelFile=No
po.datamodel = self.datamodel
po.SetupConnections()
self.Plugins[plugin.name] = po
+
+ print('PLUGIN ' + str(po))
logger.info("Loaded Plugins: %s", self.Plugins.keys())
@@ -57,6 +59,8 @@ def __init__(self, dataFile=None, harmonizationModelFile=None, SPAREModelFile=No
for num in range(len(self.Plugins)):
for key,value in self.Plugins.items():
if(num == value.getTabPosition()):
+ print('Loading tab ' + str(num))
+ print(value)
self.ui.tabWidget.insertTab(value.getTabPosition(),value,key)
break
@@ -64,7 +68,8 @@ def __init__(self, dataFile=None, harmonizationModelFile=None, SPAREModelFile=No
if dataFile is not None:
# if datafile provided on cmd line, load it
- self.Plugins['Load and Save Data'].ReadData(dataFile)
+ #self.Plugins['Table View'].ReadData(dataFile)
+ self.ReadData(dataFile)
if harmonizationModelFile is not None:
#if harmonization model file provided on cmd line, load it
@@ -75,16 +80,18 @@ def __init__(self, dataFile=None, harmonizationModelFile=None, SPAREModelFile=No
#if SPARE model file provided on cmd line, load it
#self.OnSPAREModelFileOpenClicked(SPAREModelFile)
- # Include Mac menu bar
- self.ui.actionHelp.setMenuRole(QAction.NoRole)
- self.ui.actionAbout.setMenuRole(QAction.NoRole)
+ ## Include Mac menu bar
+ #self.ui.menuFile.setMenuRole(QAction.NoRole)
+ #self.ui.actionOpen.setMenuRole(QAction.NoRole)
+ #self.ui.actionSave.setMenuRole(QAction.NoRole)
def __del__(self):
logger.info('NiBAx session ending...')
def SetupConnections(self):
+ self.actionOpen.triggered.connect(self.OnOpenClicked)
+ self.actionSave.triggered.connect(self.OnSaveClicked)
self.actionAbout.triggered.connect(self.OnAboutClicked)
- self.actionHelp.triggered.connect(self.OnHelpClicked)
def SetupUi(self):
root = os.path.dirname(__file__)
@@ -93,13 +100,61 @@ def SetupUi(self):
self.setWindowIcon(QtGui.QIcon(":/images/NiBAX Logo.png"))
self.aboutdialog = AboutDialog(self)
- def OnAboutClicked(self):
- self.aboutdialog.show()
-
- def OnHelpClicked(self):
+ #def _createMenuBar(self):
+ #menuBar = self.menuBar()
+ ## Creating menus using a QMenu object
+ #fileMenu = QMenu("&File", self)
+ #menuBar.addMenu(fileMenu)
+ ## Creating menus using a title
+ #editMenu = menuBar.addMenu("&Edit")
+ #helpMenu = menuBar.addMenu("&Help")
+
+ def ReadData(self,filename):
+ #read input data
+ dio = DataIO()
+ if filename.endswith('.pkl.gz') | filename[0].endswith('.pkl'):
+ d = dio.ReadPickleFile(filename)
+ elif filename.endswith('.csv'):
+ d = dio.ReadCSVFile(filename)
+ else:
+ d = None
+
+ #also read MUSE dictionary
+ MUSEDictNAMEtoID, MUSEDictIDtoNAME, MUSEDictDataFrame = dio.ReadMUSEDictionary()
+ self.datamodel.SetMUSEDictionaries(MUSEDictNAMEtoID, MUSEDictIDtoNAME,MUSEDictDataFrame)
+
+ #also read Derived MUSE dictionary
+ DerivedMUSEMap = dio.ReadDerivedMUSEMap()
+ self.datamodel.SetDerivedMUSEMap(DerivedMUSEMap)
+
+ #set data in model
+ #if (d is not None) and self.datamodel.IsValidData(d):
+ if (d is not None):
+ logger.info('New data read from file: %s', filename)
+ self.datamodel.SetDataFilePath(filename)
+ self.datamodel.SetData(d)
+ else:
+ logger.warning('Loaded data was not valid.')
+
+
+ def OnOpenClicked(self):
+ filename = QtWidgets.QFileDialog.getOpenFileName(None,
+ caption = 'Open data file',
+ directory = QtCore.QDir().homePath(),
+ filter = "Pickle/CSV files (*.pkl.gz *.pkl *.csv)")
+
+ if filename[0] == "":
+ logger.warning("No file was selected")
+ else:
+ self.ReadData(filename[0])
+
+ def OnSaveClicked(self):
url = QtCore.QUrl('https://github.com/CBICA/NiBAx')
QtGui.QDesktopServices.openUrl(url)
+ def OnAboutClicked(self):
+ self.aboutdialog.show()
+
def OnCloseClicked(self):
#close currently loaded data and model
QtWidgets.QApplication.quit()
diff --git a/NiBAx/mainwindow.ui b/NiBAx/mainwindow.ui
index 0819a6bf4..a95acf586 100644
--- a/NiBAx/mainwindow.ui
+++ b/NiBAx/mainwindow.ui
@@ -33,24 +33,31 @@
22
-
-
+
- About
+ Open
-
+
- Help
+ Save
+
+
+
+
+ About
diff --git a/NiBAx/plugins/agetrends/agetrends.yapsy-plugin b/NiBAx/plugins/agetrends/agetrends.yapsy-plugin.disabled
similarity index 100%
rename from NiBAx/plugins/agetrends/agetrends.yapsy-plugin
rename to NiBAx/plugins/agetrends/agetrends.yapsy-plugin.disabled
diff --git a/NiBAx/plugins/distview/__init__.py b/NiBAx/plugins/distview/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/NiBAx/plugins/distview/distview.py b/NiBAx/plugins/distview/distview.py
new file mode 100644
index 000000000..bd7e444fa
--- /dev/null
+++ b/NiBAx/plugins/distview/distview.py
@@ -0,0 +1,205 @@
+from PyQt5.QtGui import *
+from PyQt5 import QtGui, QtCore, QtWidgets, uic
+from PyQt5.QtWidgets import QMdiArea, QMdiSubWindow, QTextEdit
+import sys, os
+import pandas as pd
+from NiBAx.core.dataio import DataIO
+# import dtale
+from NiBAx.core.baseplugin import BasePlugin
+from NiBAx.core import iStagingLogger
+from NiBAx.core.gui.SearchableQComboBox import SearchableQComboBox
+from NiBAx.core.gui.CheckableQComboBox import CheckableQComboBox
+from NiBAx.core.plotcanvas import PlotCanvas
+import seaborn as sns
+import matplotlib.pyplot as plt
+import numpy as np
+import pandas as pd
+from matplotlib.cm import get_cmap
+from matplotlib.lines import Line2D
+
+logger = iStagingLogger.get_logger(__name__)
+
+class PandasModel(QtCore.QAbstractTableModel):
+ def __init__(self, data, parent=None):
+ QtCore.QAbstractTableModel.__init__(self, parent)
+ self._data = data
+ self.header_labels = None
+
+ def rowCount(self, parent=None):
+ return len(self._data.values)
+
+ def columnCount(self, parent=None):
+ return self._data.columns.size
+
+ def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
+ self.header_labels = self._data.keys()
+ if role == QtCore.Qt.DisplayRole and orientation == QtCore.Qt.Horizontal:
+ return self.header_labels[section]
+ return QtCore.QAbstractTableModel.headerData(self, section, orientation, role)
+
+ def data(self, index, role=QtCore.Qt.DisplayRole):
+ if index.isValid():
+ if role == QtCore.Qt.DisplayRole:
+ return QtCore.QVariant(str(
+ self._data.iloc[index.row()][index.column()]))
+ return QtCore.QVariant()
+
+class DistView(QtWidgets.QWidget,BasePlugin):
+
+ def __init__(self):
+ super(DistView,self).__init__()
+ self.datamodel = None
+ root = os.path.dirname(__file__)
+ self.readAdditionalInformation(root)
+ self.ui = uic.loadUi(os.path.join(root, 'distview.ui'),self)
+
+ self.mdi = self.findChild(QMdiArea, 'mdiArea')
+
+ self.ui.comboBoxXVar = SearchableQComboBox(self.ui)
+ self.ui.vlBAA.addWidget(self.ui.comboBoxXVar)
+
+ self.ui.comboBoxFilterVar = SearchableQComboBox(self.ui)
+ self.ui.vlBAC.addWidget(self.ui.comboBoxFilterVar)
+
+ self.ui.comboBoxFilterVar2 = CheckableQComboBox(self.ui)
+ self.ui.vlBAD.addWidget(self.ui.comboBoxFilterVar2)
+
+ self.ui.comboBoxHueVar = SearchableQComboBox(self.ui)
+ self.ui.vlBAE.addWidget(self.ui.comboBoxHueVar)
+
+ self.ui.comboBoxHueVar2 = CheckableQComboBox(self.ui)
+ self.ui.vlBAF.addWidget(self.ui.comboBoxHueVar2)
+
+ self.ui.wB.setMaximumWidth(300)
+
+ #self.PopulateVars()
+ #self.ui.vlB.addStretch()
+ #self.ui.vlBAB.addStretch()
+
+
+ def SetupConnections(self):
+ print('todo')
+ self.ui.plotBtn.clicked.connect(lambda: self.OnPlotBtnClicked())
+ self.datamodel.data_changed.connect(lambda: self.OnDataChanged())
+ self.datamodel.currdata_changed.connect(lambda: self.OnCurrDataChanged())
+ self.ui.comboBoxHueVar.currentIndexChanged.connect(lambda: self.OnHueIndexChanged())
+ self.ui.comboBoxFilterVar.currentIndexChanged.connect(lambda: self.OnFilterIndexChanged())
+
+ def OnFilterIndexChanged(self):
+ selFilter = self.ui.comboBoxFilterVar.currentText()
+ selFilterVals = self.datamodel.data[selFilter].unique()
+
+ if len(selFilterVals) < 20:
+ self.ui.comboBoxFilterVar2.blockSignals(True)
+ self.ui.comboBoxFilterVar2.clear()
+ self.ui.comboBoxFilterVar2.blockSignals(False)
+ self.ui.comboBoxFilterVar2.addItems(selFilterVals)
+ else:
+ print('Too many unique values for selection, skip : ' + selFilter + ' ' + str(len(selFilterVals)))
+
+ def OnHueIndexChanged(self):
+ selHue = self.ui.comboBoxHueVar.currentText()
+ selHueVals = self.datamodel.data[selHue].unique()
+
+ if len(selHueVals) < 20:
+ self.ui.comboBoxHueVar2.blockSignals(True)
+ self.ui.comboBoxHueVar2.clear()
+ self.ui.comboBoxHueVar2.blockSignals(False)
+ self.ui.comboBoxHueVar2.addItems(selHueVals)
+ else:
+ print('Too many unique values for selection, skip : ' + str(len(selHueVals)))
+
+
+ def OnPlotBtnClicked(self):
+ xVar = self.ui.comboBoxXVar.currentText()
+
+ hueVar = self.ui.comboBoxHueVar.currentText()
+ hueVarVals = self.ui.comboBoxHueVar2.listCheckedItems()
+
+ filterVar = self.ui.comboBoxFilterVar.currentText()
+ filterVarVals = self.ui.comboBoxFilterVar2.listCheckedItems()
+
+ self.plotCanvas = PlotCanvas(self.ui)
+ self.plotCanvas.axes = self.plotCanvas.fig.add_subplot(111)
+
+ sub = QMdiSubWindow()
+ sub.setWidget(self.plotCanvas)
+ self.mdi.addSubWindow(sub)
+ self.PlotData(xVar, filterVar, filterVarVals, hueVar, hueVarVals)
+ sub.show()
+ self.mdi.tileSubWindows()
+
+ def PopulateVars(self):
+ #get data column header names
+ colNames = self.datamodel.currdatacols
+
+ #add the list items to comboBox
+ for cbox in [self.ui.comboBoxXVar, self.ui.comboBoxHueVar, self.ui.comboBoxFilterVar]:
+ cbox.blockSignals(True)
+ cbox.clear()
+ cbox.blockSignals(False)
+ cbox.addItems(colNames)
+
+ ##add the list items to comboBox
+ ##self.ui.comboBoxXVar.blockSignals(True)
+ ##self.ui.comboBoxXVar.clear()
+ ##self.ui.comboBoxXVar.blockSignals(False)
+ #print('OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO')
+ #print(self.datamodel)
+ ##print(self.datamodel.currdatacols)
+ ##self.ui.comboBoxXVar.addItems(colNames)
+
+ def PopulateSelect(self):
+ #get data column header names
+ colNames = self.datamodel.GetColumnHeaderNames()
+
+ #add the list items to comboBox
+ self.ui.comboBoxSelect.blockSignals(True)
+ self.ui.comboBoxSelect.clear()
+ self.ui.comboBoxSelect.blockSignals(False)
+ self.ui.comboBoxSelect.addItems(colNames)
+
+
+ def OnDataChanged(self):
+ self.PopulateVars()
+ #self.PopulateSelect()
+ #self.PopulateTable()
+
+ def OnCurrDataChanged(self):
+ self.PopulateVars()
+
+ def PlotData(self, xVar, filterVar, filterVarVals, hueVar, hueVarVals):
+
+ # clear plot
+ self.plotCanvas.axes.clear()
+
+ ## Get data
+ data = self.datamodel.GetDataSelCols([xVar, filterVar, hueVar])
+
+ ## Filter data
+ if len(filterVarVals)>0:
+ data = data[data[filterVar].isin(filterVarVals)]
+
+ ## Get hue values
+ if len(hueVarVals)>0:
+ data = data[data[hueVar].isin(hueVarVals)]
+
+ # seaborn plot on axis
+ #a = sns.scatterplot(x=xVar, y=yVar, hue=hueVar, ax=self.plotCanvas.axes, s=5, data=data)
+
+ #sns.displot(data=data, x=xVar, hue=hueVar, kind='kde', ax=self.plotCanvas.axes)
+ sns.kdeplot(data=data, x=xVar, hue=hueVar, ax=self.plotCanvas.axes)
+ #self.plotCanvas.axes.legend(handles=b)
+
+ #self.plotCanvas.axes.yaxis.set_ticks_position('left')
+ #self.plotCanvas.axes.xaxis.set_ticks_position('bottom')
+
+ sns.despine(fig=self.plotCanvas.axes.get_figure(), trim=True)
+ self.plotCanvas.axes.get_figure().set_tight_layout(True)
+
+ self.plotCanvas.axes.set(xlabel=xVar)
+ #self.plotCanvas.axes.set(ylabel=yVar)
+
+ # refresh canvas
+ self.plotCanvas.draw()
+
diff --git a/NiBAx/plugins/distview/distview.ui b/NiBAx/plugins/distview/distview.ui
new file mode 100644
index 000000000..5c2928211
--- /dev/null
+++ b/NiBAx/plugins/distview/distview.ui
@@ -0,0 +1,237 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 906
+ 549
+
+
+
+ Form
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+
+ 8
+ 0
+
+
+
+
-
+
+
+
+
+
+
+
+ 1
+ 0
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+ 8
+
+
+
-
+
+
+ X Var
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+ 8
+
+
+
-
+
+
+ Filter Var
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+ 8
+
+
+
-
+
+
+ Hue Var
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+ 8
+
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Plot
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NiBAx/plugins/distview/distview.yapsy-plugin b/NiBAx/plugins/distview/distview.yapsy-plugin
new file mode 100644
index 000000000..c0def0a9d
--- /dev/null
+++ b/NiBAx/plugins/distview/distview.yapsy-plugin
@@ -0,0 +1,13 @@
+[Core]
+Name = Dist View
+Module = distview
+
+[Documentation]
+Author = Guray Erus
+Version = 0.1
+Website =
+Description = Dist View of Data
+
+[Tab]
+#tab position starts from 0
+Position = 2
diff --git a/NiBAx/plugins/loadsave/loadsave.yapsy-plugin b/NiBAx/plugins/loadsave/loadsave.yapsy-plugin.disabled
similarity index 100%
rename from NiBAx/plugins/loadsave/loadsave.yapsy-plugin
rename to NiBAx/plugins/loadsave/loadsave.yapsy-plugin.disabled
diff --git a/NiBAx/plugins/plotview/__init__.py b/NiBAx/plugins/plotview/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/NiBAx/plugins/plotview/plotview.py b/NiBAx/plugins/plotview/plotview.py
new file mode 100644
index 000000000..b033430e7
--- /dev/null
+++ b/NiBAx/plugins/plotview/plotview.py
@@ -0,0 +1,222 @@
+from PyQt5.QtGui import *
+from PyQt5 import QtGui, QtCore, QtWidgets, uic
+from PyQt5.QtWidgets import QMdiArea, QMdiSubWindow, QTextEdit
+import sys, os
+import pandas as pd
+from NiBAx.core.dataio import DataIO
+# import dtale
+from NiBAx.core.baseplugin import BasePlugin
+from NiBAx.core import iStagingLogger
+from NiBAx.core.gui.SearchableQComboBox import SearchableQComboBox
+from NiBAx.core.gui.CheckableQComboBox import CheckableQComboBox
+from NiBAx.core.plotcanvas import PlotCanvas
+import seaborn as sns
+import matplotlib.pyplot as plt
+import numpy as np
+import pandas as pd
+from matplotlib.cm import get_cmap
+from matplotlib.lines import Line2D
+
+logger = iStagingLogger.get_logger(__name__)
+
+class PandasModel(QtCore.QAbstractTableModel):
+ def __init__(self, data, parent=None):
+ QtCore.QAbstractTableModel.__init__(self, parent)
+ self._data = data
+ self.header_labels = None
+
+ def rowCount(self, parent=None):
+ return len(self._data.values)
+
+ def columnCount(self, parent=None):
+ return self._data.columns.size
+
+ def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
+ self.header_labels = self._data.keys()
+ if role == QtCore.Qt.DisplayRole and orientation == QtCore.Qt.Horizontal:
+ return self.header_labels[section]
+ return QtCore.QAbstractTableModel.headerData(self, section, orientation, role)
+
+ def data(self, index, role=QtCore.Qt.DisplayRole):
+ if index.isValid():
+ if role == QtCore.Qt.DisplayRole:
+ return QtCore.QVariant(str(
+ self._data.iloc[index.row()][index.column()]))
+ return QtCore.QVariant()
+
+class PlotView(QtWidgets.QWidget,BasePlugin):
+
+ def __init__(self):
+ super(PlotView,self).__init__()
+ self.datamodel = None
+ root = os.path.dirname(__file__)
+ self.readAdditionalInformation(root)
+ self.ui = uic.loadUi(os.path.join(root, 'plotview.ui'),self)
+
+ self.mdi = self.findChild(QMdiArea, 'mdiArea')
+
+ self.ui.comboBoxXVar = SearchableQComboBox(self.ui)
+ self.ui.vlBAA.addWidget(self.ui.comboBoxXVar)
+
+ self.ui.comboBoxYVar = SearchableQComboBox(self.ui)
+ self.ui.vlBAB.addWidget(self.ui.comboBoxYVar)
+
+ self.ui.comboBoxFilterVar = SearchableQComboBox(self.ui)
+ self.ui.vlBAC.addWidget(self.ui.comboBoxFilterVar)
+
+ self.ui.comboBoxFilterVar2 = CheckableQComboBox(self.ui)
+ self.ui.vlBAD.addWidget(self.ui.comboBoxFilterVar2)
+
+ self.ui.comboBoxHueVar = SearchableQComboBox(self.ui)
+ self.ui.vlBAE.addWidget(self.ui.comboBoxHueVar)
+
+ self.ui.comboBoxHueVar2 = CheckableQComboBox(self.ui)
+ self.ui.vlBAF.addWidget(self.ui.comboBoxHueVar2)
+
+ self.ui.wB.setMaximumWidth(300)
+
+ #self.PopulateVars()
+ #self.ui.vlB.addStretch()
+ #self.ui.vlBAB.addStretch()
+
+
+ def SetupConnections(self):
+ print('todo')
+ self.ui.plotBtn.clicked.connect(lambda: self.OnPlotBtnClicked())
+ self.datamodel.data_changed.connect(lambda: self.OnDataChanged())
+ self.datamodel.currdata_changed.connect(lambda: self.OnCurrDataChanged())
+ self.ui.comboBoxHueVar.currentIndexChanged.connect(lambda: self.OnHueIndexChanged())
+ self.ui.comboBoxFilterVar.currentIndexChanged.connect(lambda: self.OnFilterIndexChanged())
+
+ def OnFilterIndexChanged(self):
+ selFilter = self.ui.comboBoxFilterVar.currentText()
+ selFilterVals = self.datamodel.data[selFilter].unique()
+
+ if len(selFilterVals) < 20:
+ self.ui.comboBoxFilterVar2.blockSignals(True)
+ self.ui.comboBoxFilterVar2.clear()
+ self.ui.comboBoxFilterVar2.blockSignals(False)
+ self.ui.comboBoxFilterVar2.addItems(selFilterVals)
+ else:
+ print('Too many unique values for selection, skip : ' + selFilter + ' ' + str(len(selFilterVals)))
+
+ def OnHueIndexChanged(self):
+ selHue = self.ui.comboBoxHueVar.currentText()
+ selHueVals = self.datamodel.data[selHue].unique()
+
+ if len(selHueVals) < 20:
+ self.ui.comboBoxHueVar2.blockSignals(True)
+ self.ui.comboBoxHueVar2.clear()
+ self.ui.comboBoxHueVar2.blockSignals(False)
+ self.ui.comboBoxHueVar2.addItems(selHueVals)
+ else:
+ print('Too many unique values for selection, skip : ' + str(len(selHueVals)))
+
+
+ def OnPlotBtnClicked(self):
+ xVar = self.ui.comboBoxXVar.currentText()
+ yVar = self.ui.comboBoxYVar.currentText()
+
+ hueVar = self.ui.comboBoxHueVar.currentText()
+ hueVarVals = self.ui.comboBoxHueVar2.listCheckedItems()
+
+ filterVar = self.ui.comboBoxFilterVar.currentText()
+ filterVarVals = self.ui.comboBoxFilterVar2.listCheckedItems()
+
+ self.plotCanvas = PlotCanvas(self.ui)
+ self.plotCanvas.axes = self.plotCanvas.fig.add_subplot(111)
+
+ sub = QMdiSubWindow()
+ sub.setWidget(self.plotCanvas)
+ self.mdi.addSubWindow(sub)
+ self.PlotData(xVar, yVar, filterVar, filterVarVals, hueVar, hueVarVals)
+ sub.show()
+ self.mdi.tileSubWindows()
+
+ def PopulateVars(self):
+ #get data column header names
+ colNames = self.datamodel.currdatacols
+
+ #add the list items to comboBox
+ for cbox in [self.ui.comboBoxXVar, self.ui.comboBoxYVar, self.ui.comboBoxHueVar, self.ui.comboBoxFilterVar]:
+ cbox.blockSignals(True)
+ cbox.clear()
+ cbox.blockSignals(False)
+ cbox.addItems(colNames)
+
+ ##add the list items to comboBox
+ ##self.ui.comboBoxXVar.blockSignals(True)
+ ##self.ui.comboBoxXVar.clear()
+ ##self.ui.comboBoxXVar.blockSignals(False)
+ #print('OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO')
+ #print(self.datamodel)
+ ##print(self.datamodel.currdatacols)
+ ##self.ui.comboBoxXVar.addItems(colNames)
+
+ def PopulateSelect(self):
+ #get data column header names
+ colNames = self.datamodel.GetColumnHeaderNames()
+
+ #add the list items to comboBox
+ self.ui.comboBoxSelect.blockSignals(True)
+ self.ui.comboBoxSelect.clear()
+ self.ui.comboBoxSelect.blockSignals(False)
+ self.ui.comboBoxSelect.addItems(colNames)
+
+
+ def OnDataChanged(self):
+ self.PopulateVars()
+ #self.PopulateSelect()
+ #self.PopulateTable()
+
+ def OnCurrDataChanged(self):
+ self.PopulateVars()
+
+
+ def hue_regplot(self, data, x, y, hue, palette=None, **kwargs):
+
+ regplots = []
+ levels = data[hue].unique()
+
+ if palette is None:
+ default_colors = get_cmap('tab10')
+ palette = {k: default_colors(i) for i, k in enumerate(levels)}
+
+ legendhandls=[]
+ for key in levels:
+ regplots.append(sns.regplot(x=x, y=y, data=data[data[hue] == key], color=palette[key], **kwargs))
+ legendhandls.append(Line2D([], [], color=palette[key], label=key))
+
+ return (regplots, legendhandls)
+
+ def PlotData(self, xVar, yVar, filterVar, filterVarVals, hueVar, hueVarVals):
+
+ # clear plot
+ self.plotCanvas.axes.clear()
+
+ ## Get data
+ data = self.datamodel.GetDataSelCols([xVar, yVar, filterVar, hueVar])
+
+ ## Filter data
+ if len(filterVarVals)>0:
+ data = data[data[filterVar].isin(filterVarVals)]
+
+ ## Get hue values
+ if len(hueVarVals)>0:
+ data = data[data[hueVar].isin(hueVarVals)]
+
+ # seaborn plot on axis
+ #a = sns.scatterplot(x=xVar, y=yVar, hue=hueVar, ax=self.plotCanvas.axes, s=5, data=data)
+ a,b = self.hue_regplot(data, xVar, yVar, hueVar, ax=self.plotCanvas.axes)
+ self.plotCanvas.axes.legend(handles=b)
+ self.plotCanvas.axes.yaxis.set_ticks_position('left')
+ self.plotCanvas.axes.xaxis.set_ticks_position('bottom')
+ sns.despine(fig=self.plotCanvas.axes.get_figure(), trim=True)
+ self.plotCanvas.axes.get_figure().set_tight_layout(True)
+
+ self.plotCanvas.axes.set(xlabel=xVar)
+ self.plotCanvas.axes.set(ylabel=yVar)
+
+ # refresh canvas
+ self.plotCanvas.draw()
+
diff --git a/NiBAx/plugins/plotview/plotview.ui b/NiBAx/plugins/plotview/plotview.ui
new file mode 100644
index 000000000..c23033431
--- /dev/null
+++ b/NiBAx/plugins/plotview/plotview.ui
@@ -0,0 +1,279 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 906
+ 549
+
+
+
+ Form
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+
+ 8
+ 0
+
+
+
+
-
+
+
+
+
+
+
+
+ 1
+ 0
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+ 8
+
+
+
-
+
+
+ X Var
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+ 8
+
+
+
-
+
+
+ Y Var
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+ 8
+
+
+
-
+
+
+ Filter Var
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+ 8
+
+
+
-
+
+
+ Hue Var
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+ 8
+
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Plot
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NiBAx/plugins/plotview/plotview.yapsy-plugin b/NiBAx/plugins/plotview/plotview.yapsy-plugin
new file mode 100644
index 000000000..79329085b
--- /dev/null
+++ b/NiBAx/plugins/plotview/plotview.yapsy-plugin
@@ -0,0 +1,13 @@
+[Core]
+Name = Plot View
+Module = plotview
+
+[Documentation]
+Author = Guray Erus
+Version = 0.1
+Website =
+Description = Plot View of Data
+
+[Tab]
+#tab position starts from 0
+Position = 5
diff --git a/NiBAx/plugins/tableview/__init__.py b/NiBAx/plugins/tableview/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/NiBAx/plugins/tableview/tableview.py b/NiBAx/plugins/tableview/tableview.py
new file mode 100644
index 000000000..dfc8a75b8
--- /dev/null
+++ b/NiBAx/plugins/tableview/tableview.py
@@ -0,0 +1,153 @@
+from PyQt5.QtGui import *
+from PyQt5 import QtGui, QtCore, QtWidgets, uic
+import sys, os
+import pandas as pd
+from NiBAx.core.dataio import DataIO
+# import dtale
+from NiBAx.core.baseplugin import BasePlugin
+from NiBAx.core import iStagingLogger
+from NiBAx.core.gui.SearchableQComboBox import SearchableQComboBox
+from NiBAx.core.gui.CheckableQComboBox import CheckableQComboBox
+
+logger = iStagingLogger.get_logger(__name__)
+
+class PandasModel(QtCore.QAbstractTableModel):
+ def __init__(self, data, parent=None):
+ QtCore.QAbstractTableModel.__init__(self, parent)
+ self._data = data
+ self.header_labels = None
+
+ def rowCount(self, parent=None):
+ return len(self._data.values)
+
+ def columnCount(self, parent=None):
+ return self._data.columns.size
+
+ def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
+ self.header_labels = self._data.keys()
+ if role == QtCore.Qt.DisplayRole and orientation == QtCore.Qt.Horizontal:
+ return self.header_labels[section]
+ return QtCore.QAbstractTableModel.headerData(self, section, orientation, role)
+
+ def data(self, index, role=QtCore.Qt.DisplayRole):
+ if index.isValid():
+ if role == QtCore.Qt.DisplayRole:
+ return QtCore.QVariant(str(
+ self._data.iloc[index.row()][index.column()]))
+ return QtCore.QVariant()
+
+class TableView(QtWidgets.QWidget,BasePlugin):
+
+ def __init__(self):
+ super(TableView,self).__init__()
+ self.datamodel = None
+ root = os.path.dirname(__file__)
+ self.readAdditionalInformation(root)
+ self.ui = uic.loadUi(os.path.join(root, 'tableview.ui'),self)
+
+ self.dataView = QtWidgets.QTableView()
+ self.ui.vlA.addWidget(self.dataView)
+
+ self.ui.comboBoxSort1 = SearchableQComboBox(self.ui)
+ self.ui.vlBBAA.addWidget(self.ui.comboBoxSort1)
+
+ self.ui.comboBoxSort2 = SearchableQComboBox(self.ui)
+ self.ui.vlBBBA.addWidget(self.ui.comboBoxSort2)
+
+ #self.ui.comboBoxSelect = SearchableQComboBox(self.ui)
+ self.ui.comboBoxSelect = CheckableQComboBox(self.ui)
+ self.ui.vlBAA.addWidget(self.ui.comboBoxSelect)
+
+ self.ui.wB.setMaximumWidth(300)
+
+ # WORKAROUND: Deactivate explore button
+ #self.ui.dtale_Btn.setVisible(False)
+
+ #self.ui.vlB.addStretch()
+ #self.ui.vlBAB.addStretch()
+
+
+ def SetupConnections(self):
+ self.ui.selBtn.clicked.connect(lambda: self.OnSelBtnClicked())
+ self.ui.sortBtn.clicked.connect(lambda: self.OnSortBtnClicked())
+ self.datamodel.data_changed.connect(lambda: self.OnDataChanged())
+ self.datamodel.currdata_changed.connect(lambda: self.OnCurrDataChanged())
+
+
+ def OnSortBtnClicked(self):
+ sortCols = []
+ sortOrders = []
+
+ if self.ui.check_sort1.isChecked():
+ sortCols.append(self.ui.comboBoxSort1.currentText())
+ if self.ui.check_asc1.isChecked():
+ sortOrders.append(True)
+ else:
+ sortOrders.append(False)
+
+ if self.ui.check_sort2.isChecked():
+ sortCols.append(self.ui.comboBoxSort2.currentText())
+ if self.ui.check_asc2.isChecked():
+ sortOrders.append(True)
+ else:
+ sortOrders.append(False)
+ self.datamodel.sortCols = sortCols
+ self.datamodel.sortOrders = sortOrders
+ self.PopulateTable()
+
+ def OnSelBtnClicked(self):
+ selCols = self.ui.comboBoxSelect.listCheckedItems()
+ dtmp = self.datamodel.data
+ dtmp = dtmp[selCols]
+ self.datamodel.SetCurrData(dtmp)
+
+ print('Num cols : ' + str(len(self.datamodel.currdatacols)))
+
+ self.PopulateSort()
+ self.PopulateTable()
+
+ def PopulateTable(self):
+ if self.datamodel.data is not None:
+ sortCol = self.datamodel.sortCols
+ sortOrders = self.datamodel.sortOrders
+ if len(sortCol)>0:
+ print(sortCol)
+ print(sortOrders)
+ model = PandasModel(self.datamodel.currdata.sort_values(sortCol, ascending=sortOrders).head(20))
+ else:
+ model = PandasModel(self.datamodel.currdata.head(20))
+ self.dataView.setModel(model)
+
+ def PopulateSort(self):
+ #get data column header names
+ colNames = self.datamodel.currdatacols
+
+ #add the list items to comboBox
+ self.ui.comboBoxSort1.blockSignals(True)
+ self.ui.comboBoxSort1.clear()
+ self.ui.comboBoxSort1.blockSignals(False)
+ self.ui.comboBoxSort1.addItems(colNames)
+
+ self.ui.comboBoxSort2.blockSignals(True)
+ self.ui.comboBoxSort2.clear()
+ self.ui.comboBoxSort2.blockSignals(False)
+ self.ui.comboBoxSort2.addItems(colNames)
+
+ def PopulateSelect(self):
+ #get data column header names
+ colNames = self.datamodel.GetColumnHeaderNames()
+
+ #add the list items to comboBox
+ self.ui.comboBoxSelect.blockSignals(True)
+ self.ui.comboBoxSelect.clear()
+ self.ui.comboBoxSelect.blockSignals(False)
+ self.ui.comboBoxSelect.addItems(colNames)
+
+
+ def OnDataChanged(self):
+ self.PopulateSort()
+ self.PopulateSelect()
+ self.PopulateTable()
+
+ def OnCurrDataChanged(self):
+ self.PopulateTable()
diff --git a/NiBAx/plugins/tableview/tableview.ui b/NiBAx/plugins/tableview/tableview.ui
new file mode 100644
index 000000000..234dd0d22
--- /dev/null
+++ b/NiBAx/plugins/tableview/tableview.ui
@@ -0,0 +1,266 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 906
+ 549
+
+
+
+ Form
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+
+ 8
+ 0
+
+
+
+
+
+
+
+
+
+ 1
+ 0
+
+
+
+
-
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+ 8
+
+
+
-
+
+
+ Selected Columns
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ All
+
+
+
+ -
+
+
+ Invert
+
+
+
+ -
+
+
+ Select
+
+
+
+
+
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+ 3
+
+
+
-
+
+
+ Sort By
+
+
+
+ -
+
+
-
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Sort col1
+
+
+
+ -
+
+
+ Ascending
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
-
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Sort col2
+
+
+
+ -
+
+
+ Ascending
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Sort
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NiBAx/plugins/tableview/tableview.uinew b/NiBAx/plugins/tableview/tableview.uinew
new file mode 100644
index 000000000..5e903d304
--- /dev/null
+++ b/NiBAx/plugins/tableview/tableview.uinew
@@ -0,0 +1,59 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 400
+ 301
+
+
+
+ Form
+
+
+
+
+ 0
+ -1
+ 401
+ 301
+
+
+
+ Qt::Horizontal
+
+
+
+
+
+
+ -
+
+
+ TextLabel
+
+
+
+ -
+
+
+ -
+
+
+ TextLabel
+
+
+
+ -
+
+
+
+
+
+
+
+
+
diff --git a/NiBAx/plugins/tableview/tableview.yapsy-plugin b/NiBAx/plugins/tableview/tableview.yapsy-plugin
new file mode 100644
index 000000000..49befcc1c
--- /dev/null
+++ b/NiBAx/plugins/tableview/tableview.yapsy-plugin
@@ -0,0 +1,13 @@
+[Core]
+Name = Table View
+Module = tableview
+
+[Documentation]
+Author = Ashish Singh
+Version = 0.1
+Website =
+Description = Table View of Data
+
+[Tab]
+#tab position starts from 0
+Position = 0