@@ -580,6 +580,344 @@ def deserialize(cls, raw_bytes, location, num_bytes, num_slices, in_path):
580580        return  out 
581581
582582
583+ class  OldBranch (CascadeLeaf ):  # Branch or branches? 
584+     """ 
585+     A :doc:`uproot.writing._cascade.CascadeLeaf` for copying an old TBranch to a new TTree. ? 
586+     """ 
587+ 
588+     class_version  =  1 
589+ 
590+     def  __init__ (self , branch_data ):
591+         self ._branch_data  =  branch_data 
592+ 
593+     @property  
594+     def  allocation (self ):
595+         if  self ._allocation  is  None :
596+             self ._allocation  =  self .num_bytes 
597+         return  self ._allocation 
598+ 
599+     @allocation .setter  
600+     def  allocation (self , value ):
601+         if  self ._allocation  !=  value :
602+             self ._file_dirty  =  True 
603+             self ._allocation  =  value 
604+ 
605+     @property  
606+     def  num_bytes (self ):
607+         total  =  0 
608+         for  _ , stop  in  self ._slices :
609+             if  stop  -  1  >=  uproot .const .kStartBigFile :
610+                 total  +=  _free_format_big .size 
611+             else :
612+                 total  +=  _free_format_small .size 
613+ 
614+         if  self ._end  is  None :
615+             if  total  +  _free_format_small .size  >=  uproot .const .kStartBigFile :
616+                 total  +=  _free_format_big .size 
617+             else :
618+                 total  +=  _free_format_small .size 
619+         elif  self ._end  >=  uproot .const .kStartBigFile :
620+             total  +=  _free_format_big .size 
621+         else :
622+             total  +=  _free_format_small .size 
623+ 
624+         return  total 
625+ 
626+     def  serialize (self , out ):
627+         # superclass TNamed (Model_TNamed(uproot.model.Model)) 
628+         # superclass TAttFill 
629+         key_num_bytes  =  uproot .reading ._key_format_big .size  +  6 
630+         name_asbytes  =  self ._branch_data .tree .name .encode (errors = "surrogateescape" )
631+         title_asbytes  =  self ._branch_data .tree .title .encode (errors = "surrogateescape" )
632+         key_num_bytes  +=  (1  if  len (name_asbytes ) <  255  else  5 ) +  len (name_asbytes )
633+         key_num_bytes  +=  (1  if  len (title_asbytes ) <  255  else  5 ) +  len (title_asbytes )
634+ 
635+         any_tbranch_index  =  len (out )
636+         out .append (None )
637+         # if isinstance(self._branch_data, uproot.models.TBranchElement): 
638+ 
639+         out .append (b"TBranch\x00 " )
640+ 
641+         tbranch_index  =  len (out )
642+         out .append (None )
643+ 
644+         tbranch_tobject  =  uproot .models .TObject .Model_TObject .empty ()  # ? 
645+         # tbranch_tnamed = self._branch_data['TNamed'].serialize() # ? 
646+         tbranch_tnamed  =  uproot .models .TNamed .Model_TNamed .empty ()
647+         tbranch_tnamed ._bases .append (tbranch_tobject )
648+         tbranch_tnamed ._members ["fTitle" ] =  self ._branch_data .title 
649+         tbranch_tnamed ._serialize (
650+             out , True , self ._branch_data .name , numpy .uint32 (0x00400000 )
651+         )
652+ 
653+         # TAttFill v2, fFillColor: 0, fFillStyle: 1001 
654+         # make model TAttFill v2 with fFillColor and fFillStyle 
655+         tattfill  =  uproot .models .TAtt .Model_TAttFill_v2 .empty ()
656+         # tattfill._deeply_writable = True # ? 
657+         tattfill ._members ["fFillColor" ] =  self ._branch_data .member ("fFillColor" )
658+         tattfill ._members ["fFillStyle" ] =  self ._branch_data .member ("fFillStyle" )
659+ 
660+         out .append (tattfill .serialize (out ))
661+ 
662+         self ._branch_data .members ["metadata_start" ] =  (6  +  6  +  8  +  6 ) +  sum (
663+             len (x ) for  x  in  out  if  x  is  not None 
664+         )
665+ 
666+         # Lie about the compression level so that ROOT checks and does the right thing. 
667+         # https://github.com/root-project/root/blob/87a998d48803bc207288d90038e60ff148827664/tree/tree/src/TBasket.cxx#L560-L578 
668+         # Without this, when small buffers are left uncompressed, ROOT complains about them not being compressed. 
669+         # (I don't know where the "no, really, this is uncompressed" bit is.) 
670+ 
671+         #  Have to actually make something for if there's a TBranchElement!! 
672+ 
673+         out .append (
674+             uproot .models .TBranch ._tbranch13_format1 .pack (
675+                 self ._branch_data .member ("fCompress" ),
676+                 self ._branch_data .member ("fBasketSize" ),
677+                 self ._branch_data .member ("fEntryOffsetLen" ),
678+                 self ._branch_data .member ("fWriteBasket" ),  # fWriteBasket 
679+                 self ._branch_data .member ("fEntryNumber" ),  # fEntryNumber 
680+             )
681+         )
682+ 
683+         # fIOFeatures (TIOFeatures) 
684+         out .append (b"@\x00 \x00 \x07 \x00 \x00 \x1a \xa1 /\x10 \x00 " )
685+         # 0 to bytestring?? 
686+         out .append (
687+             uproot .models .TBranch ._tbranch13_format2 .pack (
688+                 self ._branch_data .member ("fOffset" ),
689+                 self ._branch_data .member ("fMaxBaskets" ),  # fMaxBaskets 
690+                 self ._branch_data .member ("fSplitLevel" ),
691+                 self ._branch_data .member ("fEntries" ),  # fEntries 
692+                 self ._branch_data .member ("fFirstEntry" ),
693+                 self ._branch_data .member ("fTotBytes" ),
694+                 self ._branch_data .member ("fZipBytes" ),
695+             )
696+         )
697+ 
698+         # empty TObjArray of TBranches 
699+         out .append (
700+             self ._branch_data .member ("fBranches" ).serialize (
701+                 out ,
702+             )
703+         )
704+ 
705+         subtobjarray_of_leaves_index  =  len (out )
706+         out .append (None )
707+ 
708+         # TObjArray header with fName: "", fSize: 1, fLowerBound: 0 
709+         out .append (
710+             b"\x00 \x01 \x00 \x00 \x00 \x00 \x03 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x01 \x00 \x00 \x00 \x00 " 
711+         )
712+         _dtype_to_char  =  {
713+             numpy .dtype ("bool" ): "O" ,
714+             numpy .dtype (">i1" ): "B" ,
715+             numpy .dtype (">u1" ): "b" ,
716+             numpy .dtype (">i2" ): "S" ,
717+             numpy .dtype (">u2" ): "s" ,
718+             numpy .dtype (">i4" ): "I" ,
719+             numpy .dtype (">u4" ): "i" ,
720+             numpy .dtype (">i8" ): "L" ,
721+             numpy .dtype (">u8" ): "l" ,
722+             numpy .dtype (">f4" ): "F" ,
723+             numpy .dtype (">f8" ): "D" ,
724+             numpy .dtype (">U" ): "C" ,
725+         }
726+ 
727+         absolute_location  =  key_num_bytes  +  sum (len (x ) for  x  in  out  if  x  is  not None )
728+         absolute_location  +=  8  +  6  *  (sum (1  if  x  is  None  else  0  for  x  in  out ) -  1 )
729+         tleaf_reference_number  =  absolute_location  +  2 
730+ 
731+         subany_tleaf_index  =  len (out )
732+         out .append (None )
733+         for  leaf  in  self ._branch_data .member ("fLeaves" ):
734+             # Make and serialize each leaf?? 
735+             letter_upper  =  _dtype_to_char [numpy .dtype (">i8" )]
736+             out .append (("TLeaf"  +  letter_upper ).encode () +  b"\x00 " )
737+             if  letter_upper  ==  "O" :
738+                 special_struct  =  uproot .models .TLeaf ._tleafO1_format1 
739+             elif  letter_upper  ==  "B" :
740+                 special_struct  =  uproot .models .TLeaf ._tleafb1_format1 
741+             elif  letter_upper  ==  "S" :
742+                 special_struct  =  uproot .models .TLeaf ._tleafs1_format1 
743+             elif  letter_upper  ==  "I" :
744+                 special_struct  =  uproot .models .TLeaf ._tleafi1_format1 
745+             elif  letter_upper  ==  "G" :
746+                 special_struct  =  uproot .models .TLeaf ._tleafl1_format0 
747+             elif  letter_upper  ==  "L" :
748+                 special_struct  =  uproot .models .TLeaf ._tleafl1_format0 
749+             elif  letter_upper  ==  "F" :
750+                 special_struct  =  uproot .models .TLeaf ._tleaff1_format1 
751+             elif  letter_upper  ==  "D" :
752+                 special_struct  =  uproot .models .TLeaf ._tleafd1_format1 
753+             elif  letter_upper  ==  "C" :
754+                 special_struct  =  uproot .models .TLeaf ._tleafc1_format1 
755+                 # single TLeaf 
756+ 
757+             leaf_name  =  self ._branch_data .member ("fName" ).encode (
758+                 errors = "surrogateescape" 
759+             )
760+             leaf_title  =  (
761+                 self ._branch_data .member ("fLeaves" )[0 ]
762+                 .member ("fTitle" )
763+                 .encode (errors = "surrogateescape" )
764+             )
765+             leaf_name_length  =  (1  if  len (leaf_name ) <  255  else  5 ) +  len (leaf_name )
766+             leaf_title_length  =  (1  if  len (leaf_title ) <  255  else  5 ) +  len (leaf_title )
767+ 
768+             leaf_header  =  numpy .array (
769+                 [
770+                     64 ,
771+                     0 ,
772+                     0 ,
773+                     76 ,
774+                     0 ,
775+                     1 ,
776+                     64 ,
777+                     0 ,
778+                     0 ,
779+                     54 ,
780+                     0 ,
781+                     2 ,
782+                     64 ,
783+                     0 ,
784+                     0 ,
785+                     30 ,
786+                     0 ,
787+                     1 ,
788+                     0 ,
789+                     1 ,
790+                     0 ,
791+                     0 ,
792+                     0 ,
793+                     0 ,
794+                     3 ,
795+                     0 ,
796+                     0 ,
797+                     0 ,
798+                 ],
799+                 numpy .uint8 ,
800+             )
801+             tmp  =  leaf_header [0 :4 ].view (">u4" )
802+             tmp [:] =  (
803+                 numpy .uint32 (
804+                     42  +  leaf_name_length  +  leaf_title_length  +  special_struct .size 
805+                 )
806+                 |  uproot .const .kByteCountMask 
807+             )
808+             tmp  =  leaf_header [6 :10 ].view (">u4" )
809+             tmp [:] =  (
810+                 numpy .uint32 (36  +  leaf_name_length  +  leaf_title_length )
811+                 |  uproot .const .kByteCountMask 
812+             )
813+             tmp  =  leaf_header [12 :16 ].view (">u4" )
814+             tmp [:] =  (
815+                 numpy .uint32 (12  +  leaf_name_length  +  leaf_title_length )
816+                 |  uproot .const .kByteCountMask 
817+             )
818+ 
819+             out .append (uproot ._util .tobytes (leaf_header ))
820+             if  len (leaf_name ) <  255 :
821+                 out .append (
822+                     struct .pack (">B%ds"  %  len (leaf_name ), len (leaf_name ), leaf_name )
823+                 )
824+             else :
825+                 out .append (
826+                     struct .pack (
827+                         ">BI%ds"  %  len (leaf_name ), 255 , len (leaf_name ), leaf_name 
828+                     )
829+                 )
830+             if  len (leaf_title ) <  255 :
831+                 out .append (
832+                     struct .pack (">B%ds"  %  len (leaf_title ), len (leaf_title ), leaf_title )
833+                 )
834+             else :
835+                 out .append (
836+                     struct .pack (
837+                         ">BI%ds"  %  len (leaf_title ), 255 , len (leaf_title ), leaf_title 
838+                     )
839+                 )
840+ 
841+             out .append (
842+                 uproot .models .TLeaf ._tleaf2_format0 .pack (
843+                     leaf .member ("fLen" ),
844+                     leaf .member ("fLenType" ),
845+                     leaf .member ("fOffset" ),  # fOffset 
846+                     leaf .member ("fIsRange" ),  # fIsRange 
847+                     leaf .member ("fIsUnsigned" ),
848+                 )
849+             )
850+             out .append (
851+                 uproot .serialization .serialize_object_any (
852+                     leaf .member ("fLeafCount" )  # fLeafCount 
853+                 )
854+             )
855+ 
856+             # specialized TLeaf* members (fMinimum, fMaximum) 
857+             # datum["tleaf_special_struct"] = special_struct 
858+             out .append (
859+                 special_struct .pack (
860+                     int (leaf .member ("fMinimum" )), int (leaf .member ("fMaximum" ))
861+                 )
862+             )
863+ 
864+             out [subany_tleaf_index ] =  (
865+                 uproot .serialization ._serialize_object_any_format1 .pack (
866+                     numpy .uint32 (sum (len (x ) for  x  in  out [subany_tleaf_index  +  1  :]) +  4 )
867+                     |  uproot .const .kByteCountMask ,
868+                     uproot .const .kNewClassTag ,
869+                 )
870+             )
871+ 
872+             out [subtobjarray_of_leaves_index ] =  uproot .serialization .numbytes_version (
873+                 sum (len (x ) for  x  in  out [subtobjarray_of_leaves_index  +  1  :]),
874+                 3 ,  # TObjArray 
875+             )
876+ 
877+         # empty TObjArray of fBaskets (embedded) 
878+         # TODO "fBranches, which is a TObjArray of nested TBranch instances (possibly TBranchElement)" 
879+ 
880+         out .append (
881+             b"@\x00 \x00 \x15 \x00 \x03 \x00 \x01 \x00 \x00 \x00 \x00 \x03 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 " 
882+         )
883+ 
884+         # out.append(self._branch_data.member("")) 
885+ 
886+         # assert sum(1 if x is None else 0 for x in out) == 4 
887+         self ._branch_data .members ["basket_metadata_start" ] =  (6  +  6  +  8  +  6 ) +  sum (
888+             len (x ) for  x  in  out  if  x  is  not None 
889+         )  # ? 
890+ 
891+         # speedbump and fBasketBytes 
892+         out .append (b"\x01 " )
893+         out .append (uproot ._util .tobytes (self ._branch_data .member ("fBasketBytes" )))
894+ 
895+         # speedbump and fBasketEntry 
896+         out .append (b"\x01 " )
897+         out .append (uproot ._util .tobytes (self ._branch_data .member ("fBasketEntry" )))
898+ 
899+         # speedbump and fBasketSeek 
900+         out .append (b"\x01 " )
901+         out .append (uproot ._util .tobytes (self ._branch_data .member ("fBasketSeek" )))
902+ 
903+         self ._branch_data .member ("fFileName" ).serialize ()  # name = None? 
904+ 
905+         out [tbranch_index ] =  uproot .serialization .numbytes_version (
906+             sum (len (x ) for  x  in  out [tbranch_index  +  1  :]), 13   # TBranch 
907+         )
908+ 
909+         out [any_tbranch_index ] =  (
910+             uproot .serialization ._serialize_object_any_format1 .pack (
911+                 numpy .uint32 (sum (len (x ) for  x  in  out [any_tbranch_index  +  1  :]) +  4 )
912+                 |  uproot .const .kByteCountMask ,
913+                 uproot .const .kNewClassTag ,
914+             )
915+         )
916+         return  out , tleaf_reference_number 
917+ 
918+     # def write(self, ) 
919+ 
920+ 
583921class  FreeSegments (CascadeNode ):
584922    """ 
585923    A :doc:`uproot.writing._cascade.CascadeNode` for writing a ROOT FreeSegments record. 
@@ -1710,6 +2048,7 @@ def add_tree(
17102048        field_name ,
17112049        initial_basket_capacity ,
17122050        resize_factor ,
2051+         existing_branches = None ,
17132052    ):
17142053        import  uproot .writing ._cascadetree 
17152054
@@ -1723,6 +2062,7 @@ def add_tree(
17232062            field_name ,
17242063            initial_basket_capacity ,
17252064            resize_factor ,
2065+             existing_branches ,
17262066        )
17272067        tree .write_anew (sink )
17282068        return  tree 
0 commit comments