From 1689d0b790d5cdc02b8cb989359da6bf65bb34cc Mon Sep 17 00:00:00 2001 From: shenshan Date: Mon, 6 Apr 2020 17:06:07 -0700 Subject: [PATCH 1/4] Demo for external storage --- matlab/external_storage/+external/Blob.m | 9 +++++++++ matlab/external_storage/+external/getSchema.m | 7 +++++++ matlab/external_storage/set_up_dj_config.mlx | Bin 0 -> 4187 bytes 3 files changed, 16 insertions(+) create mode 100644 matlab/external_storage/+external/Blob.m create mode 100644 matlab/external_storage/+external/getSchema.m create mode 100644 matlab/external_storage/set_up_dj_config.mlx diff --git a/matlab/external_storage/+external/Blob.m b/matlab/external_storage/+external/Blob.m new file mode 100644 index 0000000..72b5460 --- /dev/null +++ b/matlab/external_storage/+external/Blob.m @@ -0,0 +1,9 @@ +%{ +# This table is a toy example of how to save a blob field into the external location +id: int +----- +external_blob: blob@imaging +%} + +classdef Blob < dj.Manual +end \ No newline at end of file diff --git a/matlab/external_storage/+external/getSchema.m b/matlab/external_storage/+external/getSchema.m new file mode 100644 index 0000000..61e9e20 --- /dev/null +++ b/matlab/external_storage/+external/getSchema.m @@ -0,0 +1,7 @@ +function obj = getSchema +persistent schemaObject +if isempty(schemaObject) + schemaObject = dj.Schema(dj.conn, 'external', 'external'); +end +obj = schemaObject; +end diff --git a/matlab/external_storage/set_up_dj_config.mlx b/matlab/external_storage/set_up_dj_config.mlx new file mode 100644 index 0000000000000000000000000000000000000000..b5e5b26d16290d10dabbaa78436dad4ea7ef87df GIT binary patch literal 4187 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 literal 0 HcmV?d00001 From ed0ba63862000dec4c2ee371a998a8e03cf738f7 Mon Sep 17 00:00:00 2001 From: shenshan Date: Mon, 6 Apr 2020 22:59:25 -0700 Subject: [PATCH 2/4] Add instructions on saveLocal, saveGlobal and deletion from external storage. --- matlab/external_storage/set_up_dj_config.mlx | Bin 4187 -> 4429 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/matlab/external_storage/set_up_dj_config.mlx b/matlab/external_storage/set_up_dj_config.mlx index b5e5b26d16290d10dabbaa78436dad4ea7ef87df..593d69f74b23b736b090234bf9cb774e3671eb6d 100644 GIT binary patch delta 2477 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 From 3099e5a06874a446a82166bd14158f19c62361ec Mon Sep 17 00:00:00 2001 From: shenshan Date: Fri, 17 Jul 2020 11:51:52 -0700 Subject: [PATCH 3/4] Add .m version of set up dj config --- matlab/external_storage/+external/Blob.m | 2 +- matlab/external_storage/set_up_dj_config.m | 74 ++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 matlab/external_storage/set_up_dj_config.m diff --git a/matlab/external_storage/+external/Blob.m b/matlab/external_storage/+external/Blob.m index 72b5460..107ae97 100644 --- a/matlab/external_storage/+external/Blob.m +++ b/matlab/external_storage/+external/Blob.m @@ -1,4 +1,4 @@ -%{ + %{ # This table is a toy example of how to save a blob field into the external location id: int ----- diff --git a/matlab/external_storage/set_up_dj_config.m b/matlab/external_storage/set_up_dj_config.m new file mode 100644 index 0000000..4f93add --- /dev/null +++ b/matlab/external_storage/set_up_dj_config.m @@ -0,0 +1,74 @@ +%% +% This notebook introduce how to set up the external storage path in the +% configuration variable |dj.config.|You could check the default of |dj.config| +% by: + +dj.config +%% +% Now you can set up the host, user, and the password + +dj.config('databaseHost', 'host_name') +dj.config('databaseUser', 'user_name') +dj.config('databasePassword', 'password') +%% +% We next would like to set up the external location. As an example, let's +% set up an external location for calcium imaging, which is named as |imaging|. + +imaging_storage = struct('protocol', 'file',... + 'location', '~/imaging') +dj.config('stores.imaging') = imaging_storage +%% +% Now the location has already set up. We could check the storage location +% by: + +dj.config('stores.imaging') +%% +% We could save this config either locally with + +dj.config.saveLocal() +%% +% Or save globally with + +dj.config.saveGlobal() +%% +% Now let's create a schema and a table to test this location. + +dj.createSchema +%% +% give a name to this new schema, for example |external|, and link it to +% a package named |+external|. Then inside the schema, create a table called |external.Blob| +% by + +dj.new +%% +% In the file |+external/Blob.m|, we could see the definition of an external +% field to be |external_blob: blob@imaging|. |imaging| is the name of the storage +% we defined above. Now let's try insert 1 entry into this table: + +insert(external.Blob, struct('id', 1, 'external_blob', rand(10))) +%% +% | |Check the table contents: + +external.Blob +%% +% Now fetch the |external_blob |as usual: + +fetch1(external.Blob, 'external_blob') +%% +% To the user, it feels like the field is still stored in the database, +% but actually it is in the external storage, in this case ~/imaging. +% +% If deleting the entry with |del| , the entry deleted is no longer fetchable, +% but the external files are not deleted unless you clean it up manually. + +del(external.Blob) +%% +% To clean up, use the following command: + +% get the schema object +schema = external.getSchema(); +schema.external.table('imaging').delete(true,[]) +%% +% 1st delete argument is bool for deleting from external source +% +% 2nd delete argument is a number for a delete limit (optional) \ No newline at end of file From 014572a56dd00842311190d915a39487e4da319f Mon Sep 17 00:00:00 2001 From: shenshan Date: Fri, 14 Aug 2020 10:17:34 -0700 Subject: [PATCH 4/4] Fix the syntax of assigning external storage --- matlab/external_storage/set_up_dj_config.m | 4 ++-- matlab/external_storage/set_up_dj_config.mlx | Bin 4429 -> 4991 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/matlab/external_storage/set_up_dj_config.m b/matlab/external_storage/set_up_dj_config.m index 4f93add..b9023c1 100644 --- a/matlab/external_storage/set_up_dj_config.m +++ b/matlab/external_storage/set_up_dj_config.m @@ -15,8 +15,8 @@ % set up an external location for calcium imaging, which is named as |imaging|. imaging_storage = struct('protocol', 'file',... - 'location', '~/imaging') -dj.config('stores.imaging') = imaging_storage + 'location', '~/imaging'); +dj.config('stores.imaging', imaging_storage) %% % Now the location has already set up. We could check the storage location % by: diff --git a/matlab/external_storage/set_up_dj_config.mlx b/matlab/external_storage/set_up_dj_config.mlx index 593d69f74b23b736b090234bf9cb774e3671eb6d..0222a6da8ac1a45f745665adc67afa292e123f47 100644 GIT binary patch delta 2232 zcmY*bXEYlO7fvHa&BUs$H6o$*E=nkkEk>z5t7d8|B{g1zDiuPF)~v65HEZ*FQ`D-x zic+IS5qrgawdZ{2JH3DIeeS(~?!C{s=jr3SgjUo5L8B;oRCNOoNRIgxwNkK-agzf8 z01f~Ea^<`n{5>5U#nA!&PXheKg1tQZ9(tjt<-iwj>~00C5drUACSNiYSH%Zv)&U-x z+=d@Iz(AIFtUO`E1u&)A*z?5m-1AEAgN3?5d=^K(08ZhKWv1qO1`=;f8`Qe&lHf)?UVAG7asG_)l75R@ok_s+cFVz+a`( zvVVhP&*}rAxBt7Brhp~zEBg>P`o;vFyQ(||5)?sGm2dg^n2gLHw1hj3*Dsrr3Q}F8 zMAiq&g$yTp-+*n{Qb6G>SX(sohXy0Id;Q7RQIqeWr4nt;8E3nxaHw`<%&jRQ$h@ke z7Eu;MBXHca=5MJ|y{vBdDekWKPOIq&H}yAjykC_|k2xbdl$=|1v8-q)9rUatCCoy@ z>|w5L8<#OHm(-jplcAM1@d zb|-c>A-_CJGhjQ8K$55xr}3vzF~aIKo5l>7dU_j-l=-WCT)-JrNtLHg$Kqo+7`uTv zJ1URje@(Hrj`diP|K1_VfDBK(|H;o)pkY80e4*9G*+bxj;GcVBy&K>E4i^ng!tM~9 ztM4Q>xH&CSjlhvxEGFnUmU$bl(QQ3;c3aJVpqW|P^I?6|Y>y%kqVhvnA`g=dam=En zTXvsMZpg_)%gmW&WpSzlTE<-6?uW5fIt?Hr3}?7T?$&%+e>(2GdQ{Bp@j|cmhnPBl9P%tYZerjh z>d5scdSD;=3pi-K#9|&yb~-% zy7oQt3r#W>_edMJV=bLg4itI1kyUNHt~8Re*XH)KqB1?muP>!Y+GCL`a3s(+=S!XQ z-uW)cyx+N!w7 zP@R?5KJmQjGflyLCGw!-I!C?0Pn+g#n;8y4FTrxLlbaW%jSgN}9-gN~37&%A&eqk* zcvz4I7JDjMq{;k#`qkr(G_(IB> z^S9~9P0nkjoQpT&20Fz{gnyu*Rb9i%)9LQL~H99LHzO?a0gwvBa1pzoxGI%8yfK+VZ0!#M~&q#&S$ycfR>G$H^^Ix|Bqi zvL;SsiEDGD!_jyk4UZv4geIhR(>?Bw-jC1Y@p(NSpZ7nX=lk`3$@cUZ)ir{Z{F)d( z4UfTK2(Ybw>fz(Nz#!1P1_&fSpg1xumKOP64?I7dH6vGv-!m7cF*pJg|0(!s{?(`JajZaIGDpWI;>}0r;s6 z`t=ntqhF{h)Mzo~U;#Jtd;!#WP8-K*r0AUnH&>yl*v3o0)EfSUgNr{XFK<>)Wwx;o~o=c_7asfpOSYpJ)S-0}0%bWg{OT>W(W zS%$vHYnVndc>Gy*Dz2+8WJ_q37NhO*wrQQ4Wyz6vb0ih*Y-fobhE_qk%&P06mI*lZ zkrzfD23{CDGJ;$jrR<|;>;A48^hxnhvS-Nnc8WbDorx)UOj@N)IXj4!sv_xrviJ zI%+N5L%P$I@&F~0>K&tja>|qZp!}ofC!en=*A`Ed8x9nFd$Ro22L^dT07G8%G^9bB zTK&dy1|AK^1IvG&X)j`$_)nzpojN_pu@S}&W+)r;p6a)_?~SpvGFN)eOH40GY4Y8HgHC$$&~1FYK#f$A;g>WORT{UL}lCSM7KTck85i0>*wPl z*4usq-Y@EAHiwgMvy11cCXmA8y)PS!+xU}jLsTBP!rY7&rn4+MdS}<`Y9?y#=2xbk z?LRDN-9_m+Q#o9)Go1%b`sr?hxVMVEe;5_)8|OcNIcQ}dsw9+cG)V4_GJG>(DI7ZX z`gzacIF+DVEI>S1~ARHZ7_v16~2T%i>KiP`#SSk%7}xI|F*ytp#^5Euyob*S#1dTt}o-3 zGx=W5L|=Yymt4wAswyXBz3XdeUta!i*s+a}rL1WSma2V`B)B>&S`)4;gKhWy3yQx6 AV*mgE