@@ -686,7 +686,7 @@ def timestamp_names(self):
686686 return names
687687
688688 def _sim_timestamps (self , max_rate , bg_rate , emission , i_start , rs ,
689- ip_start = 0 , scale = 10 , sort = True ):
689+ ip_start = 0 , scale = 10 , sort = True , save_pos = False ):
690690 """Simulate timestamps from emission trajectories.
691691
692692 Uses attributes: `.t_step`.
@@ -702,7 +702,9 @@ def _sim_timestamps(self, max_rate, bg_rate, emission, i_start, rs,
702702 assert counts_chunk .shape == (nrows , emission .shape [1 ])
703703 max_counts = counts_chunk .max ()
704704 if max_counts == 0 :
705- return np .array ([], dtype = np .int64 ), np .array ([], dtype = np .int64 )
705+ return (np .array ([], dtype = np .int64 ), # timestamps
706+ np .array ([], dtype = np .int64 ), # particles
707+ np .array ([], dtype = np .float32 )) # positions
706708
707709 time_start = i_start * scale
708710 time_stop = time_start + counts_chunk .shape [1 ] * scale
@@ -722,51 +724,67 @@ def _sim_timestamps(self, max_rate, bg_rate, emission, i_start, rs,
722724 # Append current particle
723725 times_chunk_p .append (t )
724726 par_index_chunk_p .append (np .full (t .size , ip + ip_start , dtype = 'u1' ))
727+ if save_pos :
728+ # TODO compute and asve positions
729+ pass
725730
726731 # Merge the arrays of different particles
727732 times_chunk = np .hstack (times_chunk_p )
728733 par_index_chunk = np .hstack (par_index_chunk_p )
734+ positions_chunk = np .zeros (
735+ (times_chunk .shape [- 1 ], self .positions .shape [1 ]), dtype = np .float32 )
729736
730737 if sort :
731738 # Sort timestamps inside the merged chunk
732739 index_sort = times_chunk .argsort (kind = 'mergesort' )
733740 times_chunk = times_chunk [index_sort ]
734741 par_index_chunk = par_index_chunk [index_sort ]
742+ if save_pos :
743+ # TODO: reorder positions
744+ pass
735745
736- return times_chunk , par_index_chunk
746+ return times_chunk , par_index_chunk , positions_chunk
737747
738748 def _sim_timestamps_populations (self , emission , max_rates , populations ,
739- bg_rates , i_start , rs , scale = 10 ):
749+ bg_rates , i_start , rs , scale = 10 ,
750+ save_pos = False ):
740751 if populations is None :
741752 populations = [slice (0 , self .num_particles )]
742753
743754 # Loop for each population
744755 ts_chunk_pop_list , par_index_chunk_pop_list = [], []
756+ positions_chunk_pop_list = []
745757 # Loop through populations
746758 for rate , pop , bg in zip (max_rates , populations , bg_rates ):
747759 emission_pop = emission [pop ]
748- ts_chunk_pop , par_index_chunk_pop = \
760+ ts_chunk_pop , par_index_chunk_pop , positions_pop = \
749761 self ._sim_timestamps (
750762 rate , bg , emission_pop , i_start , ip_start = pop .start ,
751- rs = rs , scale = scale , sort = False )
763+ rs = rs , scale = scale , sort = False , save_pos = save_pos )
752764
753765 ts_chunk_pop_list .append (ts_chunk_pop )
754766 par_index_chunk_pop_list .append (par_index_chunk_pop )
767+ if save_pos :
768+ positions_chunk_pop_list .append (positions_pop )
755769
756770 # Merge populations
757771 times_chunk_s = np .hstack (ts_chunk_pop_list )
758772 par_index_chunk_s = np .hstack (par_index_chunk_pop_list )
773+ if save_pos :
774+ positions_chunk_s = np .hstack (positions_chunk_pop_list )
759775
760776 # Sort timestamps inside the merged chunk
761777 index_sort = times_chunk_s .argsort (kind = 'mergesort' )
762778 times_chunk_s = times_chunk_s [index_sort ]
763779 par_index_chunk_s = par_index_chunk_s [index_sort ]
764- return times_chunk_s , par_index_chunk_s
780+ if save_pos :
781+ positions_chunk_s = positions_chunk_s [index_sort ]
782+ return times_chunk_s , par_index_chunk_s , positions_chunk_s
765783
766784 def simulate_timestamps_mix (self , max_rates , populations , bg_rate ,
767785 rs = None , seed = 1 , chunksize = 2 ** 16 ,
768786 comp_filter = None , overwrite = False ,
769- skip_existing = False , scale = 10 ,
787+ skip_existing = False , scale = 10 , save_pos = False ,
770788 path = None , t_chunksize = None , timeslice = None ):
771789 """Compute one timestamps array for a mixture of N populations.
772790
@@ -797,6 +815,8 @@ def simulate_timestamps_mix(self, max_rates, populations, bg_rate,
797815 scale (int): `self.t_step` is multiplied by `scale` to obtain the
798816 timestamps units in seconds.
799817 path (string): folder where to save the data.
818+ save_pos (bool): if True save 3D position of each particle
819+ for each emitted photon.
800820 timeslice (float or None): timestamps are simulated until
801821 `timeslice` seconds. If None, simulate until `self.t_max`.
802822 """
@@ -814,13 +834,16 @@ def simulate_timestamps_mix(self, max_rates, populations, bg_rate,
814834 max_rates = max_rates , bg_rate = bg_rate , populations = populations ,
815835 num_particles = self .num_particles ,
816836 bg_particle = self .num_particles ,
817- overwrite = overwrite , chunksize = chunksize
837+ overwrite = overwrite , chunksize = chunksize ,
838+ save_pos = save_pos ,
818839 )
840+ if save_pos :
841+ kw .update (spatial_dims = self .positions .shape [1 ])
819842 if comp_filter is not None :
820843 kw .update (comp_filter = comp_filter )
821844 try :
822- self ._timestamps , self ._tparticles = (self . ts_store
823- .add_timestamps (** kw ))
845+ self ._timestamps , self ._tparticles , self . _tpositions = (
846+ self . ts_store .add_timestamps (** kw ))
824847 except ExistingArrayError as e :
825848 if skip_existing :
826849 print (' - Skipping already present timestamps array.' )
@@ -832,7 +855,7 @@ def simulate_timestamps_mix(self, max_rates, populations, bg_rate,
832855 self ._timestamps .attrs ['init_random_state' ] = rs .get_state ()
833856 self ._timestamps .attrs ['PyBroMo' ] = __version__
834857
835- ts_list , part_list = [], []
858+ ts_list , part_list , pos_list = [], [], []
836859 # Load emission in chunks, and save only the final timestamps
837860 bg_rates = [None ] * (len (max_rates ) - 1 ) + [bg_rate ]
838861 prev_time = 0
@@ -846,18 +869,21 @@ def simulate_timestamps_mix(self, max_rates, populations, bg_rate,
846869
847870 em_chunk = self .emission [:, i_start :i_end ]
848871
849- times_chunk_s , par_index_chunk_s = \
872+ times_chunk_s , par_index_chunk_s , positions_chunk_s = \
850873 self ._sim_timestamps_populations (
851874 em_chunk , max_rates , populations , bg_rates , i_start ,
852- rs , scale )
875+ rs , scale , save_pos = save_pos )
853876
854- # Save sorted timestamps (suffix '_s') and corresponding particles
877+ # Save sorted "photons" (suffix '_s')
855878 ts_list .append (times_chunk_s )
856879 part_list .append (par_index_chunk_s )
880+ pos_list .append (positions_chunk_s ) # it may be a list of None
857881
858- for ts , part in zip (ts_list , part_list ):
882+ for ts , part , pos in zip (ts_list , part_list , pos_list ):
859883 self ._timestamps .append (ts )
860884 self ._tparticles .append (part )
885+ if save_pos :
886+ self ._tpositions .append (pos )
861887
862888 # Save current random state so it can be resumed in the next session
863889 self .ts_group ._v_attrs ['last_random_state' ] = rs .get_state ()
@@ -933,8 +959,8 @@ def simulate_timestamps_mix_da(self, max_rates_d, max_rates_a,
933959
934960 kw .update (name = name_d , max_rates = max_rates_d , bg_rate = bg_rate_d )
935961 try :
936- self ._timestamps_d , self ._tparticles_d = (self . ts_store
937- .add_timestamps (** kw ))
962+ self ._timestamps_d , self ._tparticles_d , _ = (
963+ self . ts_store .add_timestamps (** kw ))
938964 except ExistingArrayError as e :
939965 if skip_existing :
940966 print (' - Skipping already present timestamps array.' )
@@ -944,8 +970,8 @@ def simulate_timestamps_mix_da(self, max_rates_d, max_rates_a,
944970
945971 kw .update (name = name_a , max_rates = max_rates_a , bg_rate = bg_rate_a )
946972 try :
947- self ._timestamps_a , self ._tparticles_a = (self . ts_store
948- .add_timestamps (** kw ))
973+ self ._timestamps_a , self ._tparticles_a , _ = (
974+ self . ts_store .add_timestamps (** kw ))
949975 except ExistingArrayError as e :
950976 if skip_existing :
951977 print (' - Skipping already present timestamps array.' )
@@ -972,12 +998,12 @@ def simulate_timestamps_mix_da(self, max_rates_d, max_rates_a,
972998
973999 em_chunk = self .emission [:, i_start :i_end ]
9741000
975- times_chunk_s_d , par_index_chunk_s_d = \
1001+ times_chunk_s_d , par_index_chunk_s_d , _ = \
9761002 self ._sim_timestamps_populations (
9771003 em_chunk , max_rates_d , populations , bg_rates_d , i_start ,
9781004 rs , scale )
9791005
980- times_chunk_s_a , par_index_chunk_s_a = \
1006+ times_chunk_s_a , par_index_chunk_s_a , _ = \
9811007 self ._sim_timestamps_populations (
9821008 em_chunk , max_rates_a , populations , bg_rates_a , i_start ,
9831009 rs , scale )
@@ -1057,8 +1083,8 @@ def simulate_timestamps_mix_da_online(self, max_rates_d, max_rates_a,
10571083
10581084 kw .update (name = name_d , max_rates = max_rates_d , bg_rate = bg_rate_d )
10591085 try :
1060- self ._timestamps_d , self ._tparticles_d = (self . ts_store
1061- .add_timestamps (** kw ))
1086+ self ._timestamps_d , self ._tparticles_d , _ = (
1087+ self . ts_store .add_timestamps (** kw ))
10621088 except ExistingArrayError as e :
10631089 if skip_existing :
10641090 print (' - Skipping, timestamps array already present.' )
@@ -1068,8 +1094,8 @@ def simulate_timestamps_mix_da_online(self, max_rates_d, max_rates_a,
10681094
10691095 kw .update (name = name_a , max_rates = max_rates_a , bg_rate = bg_rate_a )
10701096 try :
1071- self ._timestamps_a , self ._tparticles_a = (self . ts_store
1072- .add_timestamps (** kw ))
1097+ self ._timestamps_a , self ._tparticles_a , _ = (
1098+ self . ts_store .add_timestamps (** kw ))
10731099 except ExistingArrayError as e :
10741100 if skip_existing :
10751101 print (' - Skipping, timestamps array already present.' )
@@ -1103,12 +1129,12 @@ def simulate_timestamps_mix_da_online(self, max_rates_d, max_rates_a,
11031129 save_pos = False , radial = False ,
11041130 wrap_func = wrap_periodic )
11051131
1106- times_chunk_s_d , par_index_chunk_s_d = \
1132+ times_chunk_s_d , par_index_chunk_s_d , _ = \
11071133 self ._sim_timestamps_populations (
11081134 em_chunk , max_rates_d , populations , bg_rates_d , i_start ,
11091135 rs , scale )
11101136
1111- times_chunk_s_a , par_index_chunk_s_a = \
1137+ times_chunk_s_a , par_index_chunk_s_a , _ = \
11121138 self ._sim_timestamps_populations (
11131139 em_chunk , max_rates_a , populations , bg_rates_a , i_start ,
11141140 rs , scale )
0 commit comments